Skip to content

Commit 18d0a7e

Browse files
authored
[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.
1 parent 11ec512 commit 18d0a7e

File tree

3 files changed

+46
-17
lines changed

3 files changed

+46
-17
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
287287
return true;
288288
}
289289

290+
case CK_IntegralComplexToReal:
291+
case CK_FloatingComplexToReal:
292+
return this->emitComplexReal(SubExpr);
293+
290294
case CK_ToVoid:
291295
return discard(SubExpr);
292296

@@ -2030,7 +2034,7 @@ bool ByteCodeExprGen<Emitter>::dereference(
20302034
}
20312035

20322036
if (LV->getType()->isAnyComplexType())
2033-
return visit(LV);
2037+
return this->delegate(LV);
20342038

20352039
return false;
20362040
}
@@ -2767,22 +2771,10 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
27672771
if (!this->visit(SubExpr))
27682772
return false;
27692773
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
2770-
case UO_Real: { // __real x
2774+
case UO_Real: // __real x
27712775
if (T)
27722776
return this->delegate(SubExpr);
2773-
if (!this->visit(SubExpr))
2774-
return false;
2775-
if (!this->emitConstUint8(0, E))
2776-
return false;
2777-
if (!this->emitArrayElemPtrPopUint8(E))
2778-
return false;
2779-
2780-
// Since our _Complex implementation does not map to a primitive type,
2781-
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
2782-
if (!SubExpr->isLValue())
2783-
return this->emitLoadPop(classifyPrim(E->getType()), E);
2784-
return true;
2785-
}
2777+
return this->emitComplexReal(SubExpr);
27862778
case UO_Imag: { // __imag x
27872779
if (T) {
27882780
if (!this->discard(SubExpr))
@@ -2953,6 +2945,29 @@ bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
29532945
return false;
29542946
}
29552947

2948+
/// Emits __real(SubExpr)
2949+
template <class Emitter>
2950+
bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
2951+
assert(SubExpr->getType()->isAnyComplexType());
2952+
2953+
if (DiscardResult)
2954+
return this->discard(SubExpr);
2955+
2956+
if (!this->visit(SubExpr))
2957+
return false;
2958+
if (!this->emitConstUint8(0, SubExpr))
2959+
return false;
2960+
if (!this->emitArrayElemPtrPopUint8(SubExpr))
2961+
return false;
2962+
2963+
// Since our _Complex implementation does not map to a primitive type,
2964+
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
2965+
if (!SubExpr->isLValue())
2966+
return this->emitLoadPop(*classifyComplexElementType(SubExpr->getType()),
2967+
SubExpr);
2968+
return true;
2969+
}
2970+
29562971
/// When calling this, we have a pointer of the local-to-destroy
29572972
/// on the stack.
29582973
/// Emit destruction of record types (or arrays of record types).

clang/lib/AST/Interp/ByteCodeExprGen.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
294294
return this->classify(ElemType);
295295
}
296296

297+
bool emitComplexReal(const Expr *SubExpr);
298+
297299
bool emitRecordDestruction(const Descriptor *Desc);
298300
unsigned collectBaseOffset(const RecordType *BaseType,
299301
const RecordType *DerivedType);

clang/test/AST/Interp/complex.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
2-
// RUN: %clang_cc1 -verify=ref %s
1+
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -Wno-unused-value %s
2+
// RUN: %clang_cc1 -verify=ref -Wno-unused-value %s
33

44
// expected-no-diagnostics
55
// ref-no-diagnostics
@@ -42,6 +42,18 @@ static_assert(__real(12u) == 12u, "");
4242
static_assert(__imag(4.0) == 0.0, "");
4343
static_assert(__imag(13) == 0, "");
4444

45+
constexpr int ignoredCast() {
46+
I2;
47+
(int)I2;
48+
(float)I2;
49+
D1;
50+
(int)D1;
51+
(double)D1;
52+
return 0;
53+
}
54+
static_assert(ignoredCast() == 0, "");
55+
static_assert((int)I1 == 1, "");
56+
static_assert((float)D == 1.0f, "");
4557

4658

4759
/// Standalone complex expressions.

0 commit comments

Comments
 (0)