Author: Timm Baeder Date: 2024-01-18T13:55:04+01:00 New Revision: 18d0a7e4c0d085de4e652e359bdd6778c43ec9bf
URL: https://github.com/llvm/llvm-project/commit/18d0a7e4c0d085de4e652e359bdd6778c43ec9bf DIFF: https://github.com/llvm/llvm-project/commit/18d0a7e4c0d085de4e652e359bdd6778c43ec9bf.diff LOG: [clang][Interp] Implement ComplexToReal casts (#77294) Add a new emitComplexReal() helper function and use that for the new casts as well as the old __real implementation. 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 5839123a5b95f23..138ffed392fcac3 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -287,6 +287,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); @@ -2030,7 +2034,7 @@ bool ByteCodeExprGen<Emitter>::dereference( } if (LV->getType()->isAnyComplexType()) - return visit(LV); + return this->delegate(LV); return false; } @@ -2767,22 +2771,10 @@ 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 if (T) return this->delegate(SubExpr); - 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 if (T) { if (!this->discard(SubExpr)) @@ -2953,6 +2945,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 bbb13e97e725692..48005ce05724b54 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 1e97cc618495244..e63693a0cfaa140 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 @@ -42,6 +42,18 @@ static_assert(__real(12u) == 12u, ""); static_assert(__imag(4.0) == 0.0, ""); static_assert(__imag(13) == 0, ""); +constexpr int ignoredCast() { + I2; + (int)I2; + (float)I2; + D1; + (int)D1; + (double)D1; + return 0; +} +static_assert(ignoredCast() == 0, ""); +static_assert((int)I1 == 1, ""); +static_assert((float)D == 1.0f, ""); /// Standalone complex expressions. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits