Skip to content

Commit 1549291

Browse files
authored
[clang] Implement constexpr __builtin_bit_cast for complex types (#109981)
Fixes #94620
1 parent 949177d commit 1549291

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7237,6 +7237,7 @@ class APValueToBufferConverter {
72377237

72387238
case APValue::ComplexInt:
72397239
case APValue::ComplexFloat:
7240+
return visitComplex(Val, Ty, Offset);
72407241
case APValue::FixedPoint:
72417242
// FIXME: We should support these.
72427243

@@ -7323,6 +7324,31 @@ class APValueToBufferConverter {
73237324
return true;
73247325
}
73257326

7327+
bool visitComplex(const APValue &Val, QualType Ty, CharUnits Offset) {
7328+
const ComplexType *ComplexTy = Ty->castAs<ComplexType>();
7329+
QualType EltTy = ComplexTy->getElementType();
7330+
CharUnits EltSizeChars = Info.Ctx.getTypeSizeInChars(EltTy);
7331+
bool IsInt = Val.isComplexInt();
7332+
7333+
if (IsInt) {
7334+
if (!visitInt(Val.getComplexIntReal(), EltTy,
7335+
Offset + (0 * EltSizeChars)))
7336+
return false;
7337+
if (!visitInt(Val.getComplexIntImag(), EltTy,
7338+
Offset + (1 * EltSizeChars)))
7339+
return false;
7340+
} else {
7341+
if (!visitFloat(Val.getComplexFloatReal(), EltTy,
7342+
Offset + (0 * EltSizeChars)))
7343+
return false;
7344+
if (!visitFloat(Val.getComplexFloatImag(), EltTy,
7345+
Offset + (1 * EltSizeChars)))
7346+
return false;
7347+
}
7348+
7349+
return true;
7350+
}
7351+
73267352
bool visitVector(const APValue &Val, QualType Ty, CharUnits Offset) {
73277353
const VectorType *VTy = Ty->castAs<VectorType>();
73287354
QualType EltTy = VTy->getElementType();
@@ -7595,6 +7621,23 @@ class BufferToAPValueConverter {
75957621
return ArrayValue;
75967622
}
75977623

7624+
std::optional<APValue> visit(const ComplexType *Ty, CharUnits Offset) {
7625+
QualType ElementType = Ty->getElementType();
7626+
CharUnits ElementWidth = Info.Ctx.getTypeSizeInChars(ElementType);
7627+
bool IsInt = ElementType->isIntegerType();
7628+
7629+
std::optional<APValue> Values[2];
7630+
for (unsigned I = 0; I != 2; ++I) {
7631+
Values[I] = visitType(Ty->getElementType(), Offset + I * ElementWidth);
7632+
if (!Values[I])
7633+
return std::nullopt;
7634+
}
7635+
7636+
if (IsInt)
7637+
return APValue(Values[0]->getInt(), Values[1]->getInt());
7638+
return APValue(Values[0]->getFloat(), Values[1]->getFloat());
7639+
}
7640+
75987641
std::optional<APValue> visit(const VectorType *VTy, CharUnits Offset) {
75997642
QualType EltTy = VTy->getElementType();
76007643
unsigned NElts = VTy->getNumElements();

clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,3 +511,19 @@ constexpr bool9 bad_short_to_bool9 = __builtin_bit_cast(bool9, static_cast<unsig
511511
constexpr bool17 bad_int_to_bool17 = __builtin_bit_cast(bool17, 0x0001CAFEU);
512512

513513
}
514+
515+
namespace test_complex {
516+
constexpr _Complex unsigned test_int_complex = { 0x0C05FEFE, 0xCAFEBABE };
517+
static_assert(round_trip<_Complex unsigned>(0xCAFEBABE0C05FEFEULL), "");
518+
static_assert(bit_cast<unsigned long long>(test_int_complex) == (LITTLE_END
519+
? 0xCAFEBABE0C05FEFE
520+
: 0x0C05FEFECAFEBABE), "");
521+
static_assert(sizeof(double) == 2 * sizeof(float));
522+
struct TwoFloats { float A; float B; };
523+
constexpr _Complex float test_float_complex = {1.0f, 2.0f};
524+
constexpr TwoFloats TF = __builtin_bit_cast(TwoFloats, test_float_complex);
525+
static_assert(TF.A == 1.0f && TF.B == 2.0f);
526+
527+
constexpr double D = __builtin_bit_cast(double, test_float_complex);
528+
constexpr int M = __builtin_bit_cast(int, test_int_complex); // expected-error {{__builtin_bit_cast source size does not equal destination size}}
529+
}

0 commit comments

Comments
 (0)