llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> Reject bitcasts to pointer types unless it's to `nulltr_t` and always reject bitcasts to member pointer types. Fixes #<!-- -->156174 --- Full diff: https://github.com/llvm/llvm-project/pull/158575.diff 4 Files Affected: - (modified) clang/lib/AST/ByteCode/Compiler.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/Interp.h (+11-1) - (modified) clang/lib/AST/ByteCode/Opcodes.td (+2-2) - (modified) clang/test/AST/ByteCode/builtin-bit-cast.cpp (+14-1) ``````````diff diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 78b74acc3789d..75b3e22549f56 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -7394,7 +7394,7 @@ 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) diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index d8362ee3176a0..7b9783398e733 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -3570,16 +3570,26 @@ 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) { + 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; diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 95a44333e8e04..7af2df5318106 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -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; } diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp index 32c1f41e0e059..0f06a1e58370e 100644 --- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp +++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp @@ -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))); @@ -572,3 +571,17 @@ 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)); + + 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}} +} `````````` </details> https://github.com/llvm/llvm-project/pull/158575 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits