Skip to content

Commit 9234c42

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 66f7310 commit 9234c42

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
@@ -241,57 +241,11 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
241241

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

297251
case CK_IntegralComplexToReal:
@@ -2120,8 +2074,15 @@ bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) {
21202074
template <class Emitter>
21212075
bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
21222076
std::optional<PrimType> T = classify(E->getType());
2123-
if (!T)
2077+
if (!T) {
2078+
// Convert complex values to bool.
2079+
if (E->getType()->isAnyComplexType()) {
2080+
if (!this->visit(E))
2081+
return false;
2082+
return this->emitComplexBoolCast(E);
2083+
}
21242084
return false;
2085+
}
21252086

21262087
if (!this->visit(E))
21272088
return false;
@@ -3249,6 +3210,60 @@ bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
32493210
return true;
32503211
}
32513212

3213+
template <class Emitter>
3214+
bool ByteCodeExprGen<Emitter>::emitComplexBoolCast(const Expr *E) {
3215+
assert(!DiscardResult);
3216+
PrimType ElemT = classifyComplexElementType(E->getType());
3217+
// We emit the expression (__real(E) != 0 || __imag(E) != 0)
3218+
// for us, that means (bool)E[0] || (bool)E[1]
3219+
if (!this->emitConstUint8(0, E))
3220+
return false;
3221+
if (!this->emitArrayElemPtrUint8(E))
3222+
return false;
3223+
if (!this->emitLoadPop(ElemT, E))
3224+
return false;
3225+
if (ElemT == PT_Float) {
3226+
if (!this->emitCastFloatingIntegral(PT_Bool, E))
3227+
return false;
3228+
} else {
3229+
if (!this->emitCast(ElemT, PT_Bool, E))
3230+
return false;
3231+
}
3232+
3233+
// We now have the bool value of E[0] on the stack.
3234+
LabelTy LabelTrue = this->getLabel();
3235+
if (!this->jumpTrue(LabelTrue))
3236+
return false;
3237+
3238+
if (!this->emitConstUint8(1, E))
3239+
return false;
3240+
if (!this->emitArrayElemPtrPopUint8(E))
3241+
return false;
3242+
if (!this->emitLoadPop(ElemT, E))
3243+
return false;
3244+
if (ElemT == PT_Float) {
3245+
if (!this->emitCastFloatingIntegral(PT_Bool, E))
3246+
return false;
3247+
} else {
3248+
if (!this->emitCast(ElemT, PT_Bool, E))
3249+
return false;
3250+
}
3251+
// Leave the boolean value of E[1] on the stack.
3252+
LabelTy EndLabel = this->getLabel();
3253+
this->jump(EndLabel);
3254+
3255+
this->emitLabel(LabelTrue);
3256+
if (!this->emitPopPtr(E))
3257+
return false;
3258+
if (!this->emitConstBool(true, E))
3259+
return false;
3260+
3261+
this->fallthrough(EndLabel);
3262+
this->emitLabel(EndLabel);
3263+
3264+
return true;
3265+
}
3266+
32523267
/// When calling this, we have a pointer of the local-to-destroy
32533268
/// on the stack.
32543269
/// 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
@@ -285,6 +285,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
285285
}
286286

287287
bool emitComplexReal(const Expr *SubExpr);
288+
bool emitComplexBoolCast(const Expr *E);
288289

289290
bool emitRecordDestruction(const Descriptor *Desc);
290291
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
@@ -125,3 +125,7 @@ struct XY { int before; struct XX xx, *xp; float* after; } xy[] = {
125125
0, // all-warning {{initializer overrides prior initialization of this subobject}}
126126
&xy[2].xx.a, &xy[2].xx, &global_float
127127
};
128+
129+
const int A = ((_Complex double)1.0 ? 21 : 1);
130+
_Static_assert(A == 21, ""); // pedantic-ref-warning {{GNU extension}} \
131+
// 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)