[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.
This commit is contained in:
parent
11ec512f44
commit
18d0a7e4c0
@ -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).
|
||||
|
||||
@ -294,6 +294,8 @@ private:
|
||||
return this->classify(ElemType);
|
||||
}
|
||||
|
||||
bool emitComplexReal(const Expr *SubExpr);
|
||||
|
||||
bool emitRecordDestruction(const Descriptor *Desc);
|
||||
unsigned collectBaseOffset(const RecordType *BaseType,
|
||||
const RecordType *DerivedType);
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user