https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/77294
Add a new emitComplexReal() helper function and use that for the new casts as well as the old __real implementation. >From 1d657e65f69f3b6d4be3ce08c5f39f73d8fc04b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Mon, 8 Jan 2024 11:14:41 +0100 Subject: [PATCH] [clang][Interp] Implement ComplexToReal casts Add a new emitComplexReal() helper function and use that for the new casts as well as the old __real implementation. --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 45 ++++++++++++++++-------- clang/lib/AST/Interp/ByteCodeExprGen.h | 2 ++ clang/test/AST/Interp/complex.cpp | 16 +++++++-- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index e6b3097a80d8f7..8a4f5a83b6f081 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -280,6 +280,10 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { return true; } + case CK_IntegralComplexToReal: + case CK_FloatingComplexToReal: + return this->emitComplexReal(SubExpr); + case CK_ToVoid: return discard(SubExpr); @@ -2023,7 +2027,7 @@ bool ByteCodeExprGen<Emitter>::dereference( } if (LV->getType()->isAnyComplexType()) - return visit(LV); + return this->delegate(LV); return false; } @@ -2760,21 +2764,9 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) { if (!this->visit(SubExpr)) return false; return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E); - case UO_Real: { // __real x + case UO_Real: // __real x assert(!T); - if (!this->visit(SubExpr)) - return false; - if (!this->emitConstUint8(0, E)) - return false; - if (!this->emitArrayElemPtrPopUint8(E)) - return false; - - // Since our _Complex implementation does not map to a primitive type, - // we sometimes have to do the lvalue-to-rvalue conversion here manually. - if (!SubExpr->isLValue()) - return this->emitLoadPop(classifyPrim(E->getType()), E); - return true; - } + return this->emitComplexReal(SubExpr); case UO_Imag: { // __imag x assert(!T); if (!this->visit(SubExpr)) @@ -2941,6 +2933,29 @@ bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT, return false; } +/// Emits __real(SubExpr) +template <class Emitter> +bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) { + assert(SubExpr->getType()->isAnyComplexType()); + + if (DiscardResult) + return this->discard(SubExpr); + + if (!this->visit(SubExpr)) + return false; + if (!this->emitConstUint8(0, SubExpr)) + return false; + if (!this->emitArrayElemPtrPopUint8(SubExpr)) + return false; + + // Since our _Complex implementation does not map to a primitive type, + // we sometimes have to do the lvalue-to-rvalue conversion here manually. + if (!SubExpr->isLValue()) + return this->emitLoadPop(*classifyComplexElementType(SubExpr->getType()), + SubExpr); + 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). diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index bbb13e97e72569..48005ce05724b5 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -294,6 +294,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, return this->classify(ElemType); } + bool emitComplexReal(const Expr *SubExpr); + 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 66490e973988bb..fd5cb8395550b5 100644 --- a/clang/test/AST/Interp/complex.cpp +++ b/clang/test/AST/Interp/complex.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s -// RUN: %clang_cc1 -verify=ref %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -Wno-unused-value %s +// RUN: %clang_cc1 -verify=ref -Wno-unused-value %s // expected-no-diagnostics // ref-no-diagnostics @@ -37,6 +37,18 @@ constexpr _Complex int I2 = {}; static_assert(__real(I2) == 0, ""); static_assert(__imag(I2) == 0, ""); +constexpr int ignoredCast() { + I2; + (int)I2; + /* (float)I2; FIXME*/ + D1; + /* (int)D1; FIXME*/ + (double)D1; + return 0; +} +static_assert(ignoredCast() == 0, ""); +static_assert((int)I1 == 1, ""); + /// Standalone complex expressions. static_assert(__real((_Complex float){1.0, 3.0}) == 1.0, ""); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits