[clang] [clang][bytecode] Remove a bitcast nullptr_t special case (PR #120188)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 16 22:32:21 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
We still need to check the input pointer, so let this go through BitCastPrim.
---
Full diff: https://github.com/llvm/llvm-project/pull/120188.diff
4 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+4-12)
- (modified) clang/lib/AST/ByteCode/Interp.h (+32-24)
- (modified) clang/lib/AST/ByteCode/Opcodes.td (+4-3)
- (modified) clang/test/AST/ByteCode/builtin-bit-cast.cpp (+8)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 7f6295e126dcfe..59c77f0ce78d2b 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -6483,14 +6483,6 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
QualType ToType = E->getType();
std::optional<PrimType> ToT = classify(ToType);
- // Bitcasting TO nullptr_t is always fine.
- if (ToType->isNullPtrType()) {
- if (!this->discard(SubExpr))
- return false;
-
- return this->emitNullPtr(0, nullptr, E);
- }
-
assert(!ToType->isReferenceType());
// Prepare storage for the result in case we discard.
@@ -6523,8 +6515,8 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
return false;
}
- if (!ToT || ToT == PT_Ptr) {
- if (!this->emitBitCastPtr(E))
+ if (!ToT) {
+ if (!this->emitBitCast(E))
return false;
return DiscardResult ? this->emitPopPtr(E) : true;
}
@@ -6540,8 +6532,8 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
ToType->isSpecificBuiltinType(BuiltinType::Char_U));
uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);
- if (!this->emitBitCast(*ToT, ToTypeIsUChar || ToType->isStdByteType(),
- ResultBitWidth, TargetSemantics, E))
+ if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->isStdByteType(),
+ ResultBitWidth, TargetSemantics, E))
return false;
if (DiscardResult)
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 2a6ea69475f787..8461d1e98f9777 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3030,43 +3030,51 @@ bool CheckNewTypeMismatchArray(InterpState &S, CodePtr OpPC, const Expr *E) {
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E);
template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
- uint32_t ResultBitWidth, const llvm::fltSemantics *Sem) {
+inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
+ uint32_t ResultBitWidth,
+ const llvm::fltSemantics *Sem) {
const Pointer &FromPtr = S.Stk.pop<Pointer>();
if (!CheckLoad(S, OpPC, FromPtr))
return false;
- size_t BuffSize = ResultBitWidth / 8;
- llvm::SmallVector<std::byte> Buff(BuffSize);
- bool HasIndeterminateBits = false;
+ if constexpr (std::is_same_v<T, Pointer>) {
+ // The only pointer type we can validly bitcast to is nullptr_t.
+ S.Stk.push<Pointer>();
+ return true;
+ } else {
- Bits FullBitWidth(ResultBitWidth);
- Bits BitWidth = FullBitWidth;
+ size_t BuffSize = ResultBitWidth / 8;
+ llvm::SmallVector<std::byte> Buff(BuffSize);
+ bool HasIndeterminateBits = false;
- if constexpr (std::is_same_v<T, Floating>) {
- assert(Sem);
- BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem));
- }
+ Bits FullBitWidth(ResultBitWidth);
+ Bits BitWidth = FullBitWidth;
- if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
- HasIndeterminateBits))
- return false;
+ if constexpr (std::is_same_v<T, Floating>) {
+ assert(Sem);
+ BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem));
+ }
- if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
- return false;
+ if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
+ HasIndeterminateBits))
+ return false;
- if constexpr (std::is_same_v<T, Floating>) {
- assert(Sem);
- S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
- } else {
- assert(!Sem);
- S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
+ if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
+ return false;
+
+ if constexpr (std::is_same_v<T, Floating>) {
+ assert(Sem);
+ S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
+ } else {
+ assert(!Sem);
+ S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
+ }
+ return true;
}
- return true;
}
-inline bool BitCastPtr(InterpState &S, CodePtr OpPC) {
+inline bool BitCast(InterpState &S, CodePtr OpPC) {
const Pointer &FromPtr = S.Stk.pop<Pointer>();
Pointer &ToPtr = S.Stk.peek<Pointer>();
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 0638f8249805f8..123c21fa43eceb 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -839,13 +839,14 @@ def IsConstantContext: Opcode;
def CheckAllocations : Opcode;
def BitCastTypeClass : TypeClass {
- let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, IntAP, IntAPS, Bool, Float];
+ let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64,
+ IntAP, IntAPS, Bool, Float, Ptr];
}
-def BitCast : Opcode {
+def BitCastPrim : Opcode {
let Types = [BitCastTypeClass];
let Args = [ArgBool, ArgUint32, ArgFltSemantics];
let HasGroup = 1;
}
-def BitCastPtr : Opcode;
+def BitCast : Opcode;
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
index 8a5bef635b8fde..1428163d5d4d86 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -507,3 +507,11 @@ typedef bool bool9 __attribute__((ext_vector_type(9)));
// both-error at +2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}}
// both-note at +1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}}
constexpr unsigned short bad_bool9_to_short = __builtin_bit_cast(unsigned short, bool9{1,1,0,1,0,1,0,1,0});
+
+// both-warning at +2 {{returning reference to local temporary object}}
+// both-note at +1 {{temporary created here}}
+constexpr const long &returns_local() { return 0L; }
+
+// both-error at +2 {{constexpr variable 'test_nullptr_bad' must be initialized by a constant expression}}
+// both-note at +1 {{read of temporary whose lifetime has ended}}
+constexpr nullptr_t test_nullptr_bad = __builtin_bit_cast(nullptr_t, returns_local());
``````````
</details>
https://github.com/llvm/llvm-project/pull/120188
More information about the cfe-commits
mailing list