Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7394,7 +7394,8 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);

if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->isStdByteType(),
ResultBitWidth, TargetSemantics, E))
ResultBitWidth, TargetSemantics,
ToType.getTypePtr(), E))
return false;

if (DiscardResult)
Expand Down
15 changes: 13 additions & 2 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -3569,17 +3569,28 @@ bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E);

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
uint32_t ResultBitWidth,
const llvm::fltSemantics *Sem) {
uint32_t ResultBitWidth, const llvm::fltSemantics *Sem,
const Type *TargetType) {
const Pointer &FromPtr = S.Stk.pop<Pointer>();

if (!CheckLoad(S, OpPC, FromPtr))
return false;

if constexpr (std::is_same_v<T, Pointer>) {
if (!TargetType->isNullPtrType()) {
S.FFDiag(S.Current->getSource(OpPC),
diag::note_constexpr_bit_cast_invalid_type)
<< /*IsToType=*/true << /*IsReference=*/false << 1 /*Pointer*/;
return false;
}
// The only pointer type we can validly bitcast to is nullptr_t.
S.Stk.push<Pointer>();
return true;
} else if constexpr (std::is_same_v<T, MemberPointer>) {
S.FFDiag(S.Current->getSource(OpPC),
diag::note_constexpr_bit_cast_invalid_type)
<< /*IsToType=*/true << /*IsReference=*/false << 2 /*MemberPointer*/;
return false;
} else {

size_t BuffSize = ResultBitWidth / 8;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ByteCode/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -872,12 +872,12 @@ def CheckNull : Opcode;

def BitCastTypeClass : TypeClass {
let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64,
IntAP, IntAPS, Bool, Float, Ptr];
IntAP, IntAPS, Bool, Float, Ptr, MemberPtr];
}

def BitCastPrim : Opcode {
let Types = [BitCastTypeClass];
let Args = [ArgBool, ArgUint32, ArgFltSemantics];
let Args = [ArgBool, ArgUint32, ArgFltSemantics, ArgTypePtr];
let HasGroup = 1;
}

Expand Down
17 changes: 16 additions & 1 deletion clang/test/AST/ByteCode/builtin-bit-cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,6 @@ constexpr const intptr_t &returns_local() { return 0L; }
// both-note@+1 {{read of temporary whose lifetime has ended}}
constexpr nullptr_t test_nullptr_bad = __builtin_bit_cast(nullptr_t, returns_local());


#ifdef __SIZEOF_INT128__
namespace VectorCast {
typedef unsigned X __attribute__ ((vector_size (64)));
Expand Down Expand Up @@ -572,3 +571,19 @@ namespace VectorCast {
#endif
}
#endif

namespace ToPrimPtrs {
struct S { int foo () { return 0; } };
auto ptr = __builtin_bit_cast(int *, ((__INTPTR_TYPE__) 0));
auto nptr = __builtin_bit_cast(nullptr_t, ((__INTPTR_TYPE__)0));

constexpr auto cptr = __builtin_bit_cast(int *, ((__INTPTR_TYPE__) 0)); // both-error {{must be initialized by a constant expression}} \
// both-note {{bit_cast to a pointer type is not allowed in a constant expression}}
constexpr auto cnptr = __builtin_bit_cast(nullptr_t, ((__INTPTR_TYPE__)0));

#if !defined(_WIN32)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the Win32 carveout?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently member pointers have a different size on windows.

auto memptr = __builtin_bit_cast(int S::*, ((__INTPTR_TYPE__) 0));
constexpr auto cmemptr = __builtin_bit_cast(int S::*, ((__INTPTR_TYPE__) 0)); // both-error {{must be initialized by a constant expression}} \
// both-note {{bit_cast to a member pointer type is not allowed in a constant expression}}
#endif
}
Loading