Skip to content

Commit 1d657e6

Browse files
committed
[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.
1 parent c15e583 commit 1d657e6

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
@@ -280,6 +280,10 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
280280
return true;
281281
}
282282

283+
case CK_IntegralComplexToReal:
284+
case CK_FloatingComplexToReal:
285+
return this->emitComplexReal(SubExpr);
286+
283287
case CK_ToVoid:
284288
return discard(SubExpr);
285289

@@ -2023,7 +2027,7 @@ bool ByteCodeExprGen<Emitter>::dereference(
20232027
}
20242028

20252029
if (LV->getType()->isAnyComplexType())
2026-
return visit(LV);
2030+
return this->delegate(LV);
20272031

20282032
return false;
20292033
}
@@ -2760,21 +2764,9 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
27602764
if (!this->visit(SubExpr))
27612765
return false;
27622766
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
2763-
case UO_Real: { // __real x
2767+
case UO_Real: // __real x
27642768
assert(!T);
2765-
if (!this->visit(SubExpr))
2766-
return false;
2767-
if (!this->emitConstUint8(0, E))
2768-
return false;
2769-
if (!this->emitArrayElemPtrPopUint8(E))
2770-
return false;
2771-
2772-
// Since our _Complex implementation does not map to a primitive type,
2773-
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
2774-
if (!SubExpr->isLValue())
2775-
return this->emitLoadPop(classifyPrim(E->getType()), E);
2776-
return true;
2777-
}
2769+
return this->emitComplexReal(SubExpr);
27782770
case UO_Imag: { // __imag x
27792771
assert(!T);
27802772
if (!this->visit(SubExpr))
@@ -2941,6 +2933,29 @@ bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
29412933
return false;
29422934
}
29432935

2936+
/// Emits __real(SubExpr)
2937+
template <class Emitter>
2938+
bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
2939+
assert(SubExpr->getType()->isAnyComplexType());
2940+
2941+
if (DiscardResult)
2942+
return this->discard(SubExpr);
2943+
2944+
if (!this->visit(SubExpr))
2945+
return false;
2946+
if (!this->emitConstUint8(0, SubExpr))
2947+
return false;
2948+
if (!this->emitArrayElemPtrPopUint8(SubExpr))
2949+
return false;
2950+
2951+
// Since our _Complex implementation does not map to a primitive type,
2952+
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
2953+
if (!SubExpr->isLValue())
2954+
return this->emitLoadPop(*classifyComplexElementType(SubExpr->getType()),
2955+
SubExpr);
2956+
return true;
2957+
}
2958+
29442959
/// When calling this, we have a pointer of the local-to-destroy
29452960
/// on the stack.
29462961
/// 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
@@ -37,6 +37,18 @@ constexpr _Complex int I2 = {};
3737
static_assert(__real(I2) == 0, "");
3838
static_assert(__imag(I2) == 0, "");
3939

40+
constexpr int ignoredCast() {
41+
I2;
42+
(int)I2;
43+
/* (float)I2; FIXME*/
44+
D1;
45+
/* (int)D1; FIXME*/
46+
(double)D1;
47+
return 0;
48+
}
49+
static_assert(ignoredCast() == 0, "");
50+
static_assert((int)I1 == 1, "");
51+
4052

4153
/// Standalone complex expressions.
4254
static_assert(__real((_Complex float){1.0, 3.0}) == 1.0, "");

0 commit comments

Comments
 (0)