https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/79452
>From 720f2f869a11dd7c905f8d91180f3eb517ab9279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Thu, 25 Jan 2024 15:20:52 +0100 Subject: [PATCH] [clang][Interp] Handle complex values in visitBool() In C++, we get a ComplexToBool cast, but we might not in C. --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 118 +++++++++++++---------- clang/lib/AST/Interp/ByteCodeExprGen.h | 1 + clang/test/AST/Interp/c.c | 11 +++ clang/test/AST/Interp/complex.cpp | 2 + 4 files changed, 82 insertions(+), 50 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 2fdc6f4f32bed9..d4b285941d46d1 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -241,57 +241,11 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { case CK_IntegralComplexToBoolean: case CK_FloatingComplexToBoolean: { - PrimType ElemT = classifyComplexElementType(SubExpr->getType()); - // We emit the expression (__real(E) != 0 || __imag(E) != 0) - // for us, that means (bool)E[0] || (bool)E[1] + if (DiscardResult) + return this->discard(SubExpr); 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 (ElemT == PT_Float) { - if (!this->emitCastFloatingIntegral(PT_Bool, CE)) - return false; - } else { - 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 (ElemT == PT_Float) { - if (!this->emitCastFloatingIntegral(PT_Bool, CE)) - return false; - } else { - 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; + return this->emitComplexBoolCast(SubExpr); } case CK_IntegralComplexToReal: @@ -2223,8 +2177,15 @@ bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) { template <class Emitter> bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) { std::optional<PrimType> T = classify(E->getType()); - if (!T) + if (!T) { + // Convert complex values to bool. + if (E->getType()->isAnyComplexType()) { + if (!this->visit(E)) + return false; + return this->emitComplexBoolCast(E); + } return false; + } if (!this->visit(E)) return false; @@ -3383,6 +3344,63 @@ bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) { return true; } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::emitComplexBoolCast(const Expr *E) { + assert(!DiscardResult); + PrimType ElemT = classifyComplexElementType(E->getType()); + // We emit the expression (__real(E) != 0 || __imag(E) != 0) + // for us, that means (bool)E[0] || (bool)E[1] + if (!this->emitConstUint8(0, E)) + return false; + if (!this->emitArrayElemPtrUint8(E)) + return false; + if (!this->emitLoadPop(ElemT, E)) + return false; + if (ElemT == PT_Float) { + if (!this->emitCastFloatingIntegral(PT_Bool, E)) + return false; + } else { + if (!this->emitCast(ElemT, PT_Bool, E)) + 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, E)) + return false; + if (!this->emitArrayElemPtrPopUint8(E)) + return false; + if (!this->emitLoadPop(ElemT, E)) + return false; + if (ElemT == PT_Float) { + if (!this->emitCastFloatingIntegral(PT_Bool, E)) + return false; + } else { + if (!this->emitCast(ElemT, PT_Bool, E)) + 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(E)) + return false; + if (!this->emitConstBool(true, E)) + return false; + + this->fallthrough(EndLabel); + this->emitLabel(EndLabel); + + return true; +} + +/// When calling this, we have a pointer of the local-to-destroy +/// on the stack. +/// Emit destruction of record types (or arrays of record types). template <class Emitter> bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Record *R) { assert(R); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 3ede86a6979eea..4c88e33b3ece47 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -289,6 +289,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, } bool emitComplexReal(const Expr *SubExpr); + bool emitComplexBoolCast(const Expr *E); bool emitRecordDestruction(const Record *R); bool emitDestruction(const Descriptor *Desc); diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index fe540dc83918fa..a390bc8e11c6e1 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -150,3 +150,14 @@ void bar_0(void) { *(int *)(&S.a) = 0; // all-warning {{cast from 'const int *' to 'int *' drops const qualifier}} *(int *)(&S.b) = 0; // all-warning {{cast from 'const int *' to 'int *' drops const qualifier}} } + +/// Complex-to-bool casts. +const int A = ((_Complex double)1.0 ? 21 : 1); +_Static_assert(A == 21, ""); // pedantic-ref-warning {{GNU extension}} \ + // pedantic-expected-warning {{GNU extension}} +const int CTI1 = ((_Complex double){0.0, 1.0}); +_Static_assert(CTI1 == 0, ""); +const _Bool CTB2 = (_Bool)(_Complex double){0.0, 1.0}; +_Static_assert(CTB2, ""); +const _Bool CTB3 = (_Complex double){0.0, 1.0}; +_Static_assert(CTB3, ""); diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp index 9fdaabd9081d56..612a94b31171b9 100644 --- a/clang/test/AST/Interp/complex.cpp +++ b/clang/test/AST/Interp/complex.cpp @@ -77,6 +77,8 @@ constexpr int ignored() { (int)D1; (double)D1; (_Complex float)I2; + (bool)D1; + (bool)I2; return 0; } static_assert(ignored() == 0, ""); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits