Skip to content

Commit bb4ec70

Browse files
committed
[clang][Interp] Handle complex values in visitBool()
In C++, we get a ComplexToBool cast, but we might not in C.
1 parent a0727e2 commit bb4ec70

File tree

4 files changed

+72
-50
lines changed

4 files changed

+72
-50
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -239,57 +239,11 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
239239

240240
case CK_IntegralComplexToBoolean:
241241
case CK_FloatingComplexToBoolean: {
242-
PrimType ElemT = classifyComplexElementType(SubExpr->getType());
243-
// We emit the expression (__real(E) != 0 || __imag(E) != 0)
244-
// for us, that means (bool)E[0] || (bool)E[1]
242+
if (DiscardResult)
243+
return this->discard(SubExpr);
245244
if (!this->visit(SubExpr))
246245
return false;
247-
if (!this->emitConstUint8(0, CE))
248-
return false;
249-
if (!this->emitArrayElemPtrUint8(CE))
250-
return false;
251-
if (!this->emitLoadPop(ElemT, CE))
252-
return false;
253-
if (ElemT == PT_Float) {
254-
if (!this->emitCastFloatingIntegral(PT_Bool, CE))
255-
return false;
256-
} else {
257-
if (!this->emitCast(ElemT, PT_Bool, CE))
258-
return false;
259-
}
260-
261-
// We now have the bool value of E[0] on the stack.
262-
LabelTy LabelTrue = this->getLabel();
263-
if (!this->jumpTrue(LabelTrue))
264-
return false;
265-
266-
if (!this->emitConstUint8(1, CE))
267-
return false;
268-
if (!this->emitArrayElemPtrPopUint8(CE))
269-
return false;
270-
if (!this->emitLoadPop(ElemT, CE))
271-
return false;
272-
if (ElemT == PT_Float) {
273-
if (!this->emitCastFloatingIntegral(PT_Bool, CE))
274-
return false;
275-
} else {
276-
if (!this->emitCast(ElemT, PT_Bool, CE))
277-
return false;
278-
}
279-
// Leave the boolean value of E[1] on the stack.
280-
LabelTy EndLabel = this->getLabel();
281-
this->jump(EndLabel);
282-
283-
this->emitLabel(LabelTrue);
284-
if (!this->emitPopPtr(CE))
285-
return false;
286-
if (!this->emitConstBool(true, CE))
287-
return false;
288-
289-
this->fallthrough(EndLabel);
290-
this->emitLabel(EndLabel);
291-
292-
return true;
246+
return this->emitComplexBoolCast(SubExpr);
293247
}
294248

295249
case CK_IntegralComplexToReal:
@@ -2055,8 +2009,15 @@ bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) {
20552009
template <class Emitter>
20562010
bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
20572011
std::optional<PrimType> T = classify(E->getType());
2058-
if (!T)
2012+
if (!T) {
2013+
// Convert complex values to bool.
2014+
if (E->getType()->isAnyComplexType()) {
2015+
if (!this->visit(E))
2016+
return false;
2017+
return this->emitComplexBoolCast(E);
2018+
}
20592019
return false;
2020+
}
20602021

20612022
if (!this->visit(E))
20622023
return false;
@@ -3150,6 +3111,60 @@ bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
31503111
return true;
31513112
}
31523113

3114+
template <class Emitter>
3115+
bool ByteCodeExprGen<Emitter>::emitComplexBoolCast(const Expr *E) {
3116+
assert(!DiscardResult);
3117+
PrimType ElemT = classifyComplexElementType(E->getType());
3118+
// We emit the expression (__real(E) != 0 || __imag(E) != 0)
3119+
// for us, that means (bool)E[0] || (bool)E[1]
3120+
if (!this->emitConstUint8(0, E))
3121+
return false;
3122+
if (!this->emitArrayElemPtrUint8(E))
3123+
return false;
3124+
if (!this->emitLoadPop(ElemT, E))
3125+
return false;
3126+
if (ElemT == PT_Float) {
3127+
if (!this->emitCastFloatingIntegral(PT_Bool, E))
3128+
return false;
3129+
} else {
3130+
if (!this->emitCast(ElemT, PT_Bool, E))
3131+
return false;
3132+
}
3133+
3134+
// We now have the bool value of E[0] on the stack.
3135+
LabelTy LabelTrue = this->getLabel();
3136+
if (!this->jumpTrue(LabelTrue))
3137+
return false;
3138+
3139+
if (!this->emitConstUint8(1, E))
3140+
return false;
3141+
if (!this->emitArrayElemPtrPopUint8(E))
3142+
return false;
3143+
if (!this->emitLoadPop(ElemT, E))
3144+
return false;
3145+
if (ElemT == PT_Float) {
3146+
if (!this->emitCastFloatingIntegral(PT_Bool, E))
3147+
return false;
3148+
} else {
3149+
if (!this->emitCast(ElemT, PT_Bool, E))
3150+
return false;
3151+
}
3152+
// Leave the boolean value of E[1] on the stack.
3153+
LabelTy EndLabel = this->getLabel();
3154+
this->jump(EndLabel);
3155+
3156+
this->emitLabel(LabelTrue);
3157+
if (!this->emitPopPtr(E))
3158+
return false;
3159+
if (!this->emitConstBool(true, E))
3160+
return false;
3161+
3162+
this->fallthrough(EndLabel);
3163+
this->emitLabel(EndLabel);
3164+
3165+
return true;
3166+
}
3167+
31533168
/// When calling this, we have a pointer of the local-to-destroy
31543169
/// on the stack.
31553170
/// Emit destruction of record types (or arrays of record types).

clang/lib/AST/Interp/ByteCodeExprGen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
283283
}
284284

285285
bool emitComplexReal(const Expr *SubExpr);
286+
bool emitComplexBoolCast(const Expr *E);
286287

287288
bool emitRecordDestruction(const Descriptor *Desc);
288289
unsigned collectBaseOffset(const RecordType *BaseType,

clang/test/AST/Interp/c.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,7 @@ _Static_assert(sizeof(name2) == 0, ""); // expected-error {{failed}} \
129129
// expected-note {{evaluates to}} \
130130
// pedantic-expected-error {{failed}} \
131131
// pedantic-expected-note {{evaluates to}}
132+
133+
const int A = ((_Complex double)1.0 ? 21 : 1);
134+
_Static_assert(A == 21, ""); // pedantic-ref-warning {{GNU extension}} \
135+
// pedantic-expected-warning {{GNU extension}}

clang/test/AST/Interp/complex.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ constexpr int ignored() {
7777
(int)D1;
7878
(double)D1;
7979
(_Complex float)I2;
80+
(bool)D1;
81+
(bool)I2;
8082
return 0;
8183
}
8284
static_assert(ignored() == 0, "");

0 commit comments

Comments
 (0)