Skip to content

Commit 797fee6

Browse files
committed
[clang][Interp] Start supporting complex types
Differential Revision: https://reviews.llvm.org/D146408
1 parent d0f5039 commit 797fee6

File tree

4 files changed

+89
-2
lines changed

4 files changed

+89
-2
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,22 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
671671
return true;
672672
}
673673

674+
if (T->isAnyComplexType()) {
675+
unsigned InitIndex = 0;
676+
for (const Expr *Init : E->inits()) {
677+
PrimType InitT = classifyPrim(Init->getType());
678+
679+
if (!this->visit(Init))
680+
return false;
681+
682+
if (!this->emitInitElem(InitT, InitIndex, E))
683+
return false;
684+
++InitIndex;
685+
}
686+
assert(InitIndex == 2);
687+
return true;
688+
}
689+
674690
return false;
675691
}
676692

@@ -2550,8 +2566,22 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
25502566
if (!this->visit(SubExpr))
25512567
return false;
25522568
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
2553-
case UO_Real: // __real x
2554-
case UO_Imag: // __imag x
2569+
case UO_Real: { // __real x
2570+
assert(!T);
2571+
if (!this->visit(SubExpr))
2572+
return false;
2573+
if (!this->emitConstUint8(0, E))
2574+
return false;
2575+
return this->emitArrayElemPtrPopUint8(E);
2576+
}
2577+
case UO_Imag: { // __imag x
2578+
assert(!T);
2579+
if (!this->visit(SubExpr))
2580+
return false;
2581+
if (!this->emitConstUint8(1, E))
2582+
return false;
2583+
return this->emitArrayElemPtrPopUint8(E);
2584+
}
25552585
case UO_Extension:
25562586
return this->delegate(SubExpr);
25572587
case UO_Coawait:

clang/lib/AST/Interp/Context.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ std::optional<PrimType> Context::classify(QualType T) const {
9292
if (T->isBooleanType())
9393
return PT_Bool;
9494

95+
if (T->isAnyComplexType())
96+
return std::nullopt;
97+
9598
if (T->isSignedIntegerOrEnumerationType()) {
9699
switch (Ctx.getIntWidth(T)) {
97100
case 64:

clang/lib/AST/Interp/EvalEmitter.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,27 @@ bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
208208
}
209209
return Ok;
210210
}
211+
212+
// Complex types.
213+
if (const auto *CT = Ty->getAs<ComplexType>()) {
214+
QualType ElemTy = CT->getElementType();
215+
std::optional<PrimType> ElemT = Ctx.classify(ElemTy);
216+
assert(ElemT);
217+
218+
if (ElemTy->isIntegerType()) {
219+
INT_TYPE_SWITCH(*ElemT, {
220+
auto V1 = Ptr.atIndex(0).deref<T>();
221+
auto V2 = Ptr.atIndex(1).deref<T>();
222+
Result = APValue(V1.toAPSInt(), V2.toAPSInt());
223+
return true;
224+
});
225+
} else if (ElemTy->isFloatingType()) {
226+
Result = APValue(Ptr.atIndex(0).deref<Floating>().getAPFloat(),
227+
Ptr.atIndex(1).deref<Floating>().getAPFloat());
228+
return true;
229+
}
230+
return false;
231+
}
211232
llvm_unreachable("invalid value to return");
212233
};
213234

clang/test/AST/Interp/complex.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
2+
// RUN: %clang_cc1 -verify=ref %s
3+
4+
// expected-no-diagnostics
5+
// ref-no-diagnostics
6+
7+
constexpr _Complex double z1 = {1.0, 2.0};
8+
static_assert(__real(z1) == 1.0, "");
9+
static_assert(__imag(z1) == 2.0, "");
10+
11+
constexpr double setter() {
12+
_Complex float d = {1.0, 2.0};
13+
14+
__imag(d) = 4.0;
15+
return __imag(d);
16+
}
17+
static_assert(setter() == 4, "");
18+
19+
constexpr _Complex double getter() {
20+
return {1.0, 3.0};
21+
}
22+
constexpr _Complex double D = getter();
23+
static_assert(__real(D) == 1.0, "");
24+
static_assert(__imag(D) == 3.0, "");
25+
26+
27+
constexpr _Complex int I1 = {1, 2};
28+
static_assert(__real(I1) == 1, "");
29+
static_assert(__imag(I1) == 2, "");
30+
31+
32+
/// FIXME: This should work in the new interpreter as well.
33+
// constexpr _Complex _BitInt(8) A = 0;// = {4};

0 commit comments

Comments
 (0)