Skip to content

Commit 6931bad

Browse files
authored
[clang][bytecode] Fix bit casts to IntAP types (#158509)
They were left out. Fixes #153920
1 parent 03c356c commit 6931bad

File tree

2 files changed

+62
-7
lines changed

2 files changed

+62
-7
lines changed

clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -441,13 +441,27 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
441441
if (llvm::sys::IsBigEndianHost)
442442
swapBytes(Memory.get(), FullBitWidth.roundToBytes());
443443

444-
BITCAST_TYPE_SWITCH_FIXED_SIZE(T, {
445-
if (BitWidth.nonZero())
446-
P.deref<T>() = T::bitcastFromMemory(Memory.get(), T::bitWidth())
447-
.truncate(BitWidth.getQuantity());
448-
else
449-
P.deref<T>() = T::zero();
450-
});
444+
if (T == PT_IntAPS) {
445+
P.deref<IntegralAP<true>>() =
446+
S.allocAP<IntegralAP<true>>(FullBitWidth.getQuantity());
447+
IntegralAP<true>::bitcastFromMemory(Memory.get(),
448+
FullBitWidth.getQuantity(),
449+
&P.deref<IntegralAP<true>>());
450+
} else if (T == PT_IntAP) {
451+
P.deref<IntegralAP<false>>() =
452+
S.allocAP<IntegralAP<false>>(FullBitWidth.getQuantity());
453+
IntegralAP<false>::bitcastFromMemory(Memory.get(),
454+
FullBitWidth.getQuantity(),
455+
&P.deref<IntegralAP<false>>());
456+
} else {
457+
BITCAST_TYPE_SWITCH_FIXED_SIZE(T, {
458+
if (BitWidth.nonZero())
459+
P.deref<T>() = T::bitcastFromMemory(Memory.get(), T::bitWidth())
460+
.truncate(BitWidth.getQuantity());
461+
else
462+
P.deref<T>() = T::zero();
463+
});
464+
}
451465
P.initialize();
452466
return true;
453467
});

clang/test/AST/ByteCode/builtin-bit-cast.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,44 @@ constexpr const intptr_t &returns_local() { return 0L; }
529529
// both-error@+2 {{constexpr variable 'test_nullptr_bad' must be initialized by a constant expression}}
530530
// both-note@+1 {{read of temporary whose lifetime has ended}}
531531
constexpr nullptr_t test_nullptr_bad = __builtin_bit_cast(nullptr_t, returns_local());
532+
533+
namespace VectorCast {
534+
typedef unsigned X __attribute__ ((vector_size (64)));
535+
typedef unsigned __int128 Y __attribute__ ((vector_size (64)));
536+
constexpr int test() {
537+
X x = {0};
538+
Y y = x;
539+
540+
X x2 = y;
541+
542+
return 0;
543+
}
544+
static_assert(test() == 0);
545+
546+
typedef int X2 __attribute__ ((vector_size (64)));
547+
typedef __int128 Y2 __attribute__ ((vector_size (64)));
548+
constexpr int test2() {
549+
X2 x = {0};
550+
Y2 y = x;
551+
552+
X2 x2 = y;
553+
554+
return 0;
555+
}
556+
static_assert(test2() == 0);
557+
558+
struct S {
559+
unsigned __int128 a : 3;
560+
};
561+
constexpr S s = __builtin_bit_cast(S, (__int128)12); // ref-error {{must be initialized by a constant expression}} \
562+
// ref-note {{constexpr bit_cast involving bit-field is not yet supported}} \
563+
// ref-note {{declared here}}
564+
#if LITTLE_END
565+
static_assert(s.a == 4); // ref-error {{not an integral constant expression}} \
566+
// ref-note {{initializer of 's' is not a constant expression}}
567+
#else
568+
static_assert(s.a == 0); // ref-error {{not an integral constant expression}} \
569+
// ref-note {{initializer of 's' is not a constant expression}}
570+
#endif
571+
572+
}

0 commit comments

Comments
 (0)