llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> This is an alternative approach to https://github.com/llvm/llvm-project/pull/169769. We leave the old `Integral<Bits, Signed>` intact and don't increase its size at all, but then introduce a new `IntegralOrPtr<Bits, Signed>`, which either holds its value _or_ a pointer and an offset. To support address-label-diffs, the offset is always pointer sized as well, making everything `>= 32` bits `sizeof(void*) + sizeof(void*) + sizeof(uint8_t)` in size. The old approach did not work out in the end because we need to be able to do arithmetic (but essentially just `+` and `-`) on the offsets of such integers-that-are-actually-pointers. c-t-t-: https://llvm-compile-time-tracker.com/compare.php?from=e7448c3f4088cae61cb1bf8ade1a4a79d7cc4dbb&to=4aa23d5b4d8e6c43b0cf846f18f34ea967895fe5&stat=instructions:u --- Patch is 60.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/185028.diff 33 Files Affected: - (modified) clang/lib/AST/ByteCode/Boolean.h (+1-2) - (modified) clang/lib/AST/ByteCode/Context.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/Descriptor.cpp (+7) - (modified) clang/lib/AST/ByteCode/Descriptor.h (+5) - (modified) clang/lib/AST/ByteCode/Integral.h (+372-10) - (modified) clang/lib/AST/ByteCode/IntegralAP.h (+1) - (modified) clang/lib/AST/ByteCode/Interp.cpp (+27-13) - (modified) clang/lib/AST/ByteCode/Interp.h (+206-9) - (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+26-34) - (modified) clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp (+10-4) - (modified) clang/lib/AST/ByteCode/InterpStack.h (+5-8) - (modified) clang/lib/AST/ByteCode/Pointer.cpp (+9) - (modified) clang/lib/AST/ByteCode/Pointer.h (+3-1) - (modified) clang/lib/AST/ByteCode/PrimType.h (+28-4) - (modified) clang/lib/AST/ByteCode/Primitives.h (+8) - (added) clang/test/AST/ByteCode/addr-label-diff.c (+19) - (added) clang/test/AST/ByteCode/addr-label-diff.cpp (+16) - (modified) clang/test/AST/ByteCode/builtin-bit-cast.cpp (+8) - (modified) clang/test/AST/ByteCode/const-eval.c (+6-3) - (modified) clang/test/AST/ByteCode/cxx11.cpp (+12) - (added) clang/test/AST/ByteCode/int-as-ptr-arith.c (+17) - (modified) clang/test/CodeGen/const-init.c (+1) - (modified) clang/test/CodeGen/const-label-addr.c (+1) - (modified) clang/test/CodeGen/statements.c (+1) - (modified) clang/test/CodeGen/staticinit.c (+1) - (modified) clang/test/CodeGenCXX/2008-05-07-CrazyOffsetOf.cpp (+1) - (modified) clang/test/CodeGenCXX/const-init-cxx11.cpp (+3) - (modified) clang/test/CodeGenCXX/const-init.cpp (+6) - (modified) clang/test/Sema/array-init.c (+2) - (modified) clang/test/Sema/compound-literal.c (+1) - (modified) clang/test/Sema/const-ptr-int-ptr-cast.c (+1) - (modified) clang/test/Sema/init.c (+1) - (modified) clang/test/SemaCXX/constexpr-string.cpp (+1) ``````````diff diff --git a/clang/lib/AST/ByteCode/Boolean.h b/clang/lib/AST/ByteCode/Boolean.h index fd8d546656881..09eefee14a854 100644 --- a/clang/lib/AST/ByteCode/Boolean.h +++ b/clang/lib/AST/ByteCode/Boolean.h @@ -61,11 +61,10 @@ class Boolean final { bool isMin() const { return isZero(); } constexpr static bool isMinusOne() { return false; } - constexpr static bool isSigned() { return false; } - constexpr static bool isNegative() { return false; } constexpr static bool isPositive() { return !isNegative(); } + constexpr static bool isNumber() { return true; } ComparisonCategoryResult compare(const Boolean &RHS) const { return Compare(V, RHS.V); diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp index 879d51e6a2c3e..cc391ba3327f8 100644 --- a/clang/lib/AST/ByteCode/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -186,7 +186,7 @@ bool Context::evaluateStringRepr(State &Parent, const Expr *SizeExpr, return false; // Must be char. - if (Ptr.getFieldDesc()->getElemSize() != 1 /*bytes*/) + if (Ptr.getFieldDesc()->getElemDataSize() != 1 /*bytes*/) return false; if (Size > Ptr.getNumElems()) { diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp index 5ebc726328fb7..6a192cad9bca2 100644 --- a/clang/lib/AST/ByteCode/Descriptor.cpp +++ b/clang/lib/AST/ByteCode/Descriptor.cpp @@ -483,3 +483,10 @@ bool Descriptor::hasTrivialDtor() const { } bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); } + +unsigned Descriptor::getElemDataSize() const { + if ((isPrimitive() || isPrimitiveArray()) && isIntegralType(getPrimType())) { + FIXED_SIZE_INT_TYPE_SWITCH(getPrimType(), { return T::bitWidth() / 8; }); + } + return ElemSize; +} diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h index b052971733567..9046801f4ebef 100644 --- a/clang/lib/AST/ByteCode/Descriptor.h +++ b/clang/lib/AST/ByteCode/Descriptor.h @@ -246,6 +246,11 @@ struct Descriptor final { unsigned getAllocSize() const { return AllocSize; } /// returns the size of an element when the structure is viewed as an array. unsigned getElemSize() const { return ElemSize; } + /// Returns the element data size, i.e. not what the size of + /// our primitive data type is, but what the data size of that is. + /// E.g., for PT_SInt32, that's 4 bytes. + unsigned getElemDataSize() const; + /// Returns the size of the metadata. unsigned getMetadataSize() const { return MDSize; } diff --git a/clang/lib/AST/ByteCode/Integral.h b/clang/lib/AST/ByteCode/Integral.h index e90f1a9a74e1c..82b62f7969d12 100644 --- a/clang/lib/AST/ByteCode/Integral.h +++ b/clang/lib/AST/ByteCode/Integral.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_AST_INTERP_INTEGRAL_H #include "clang/AST/APValue.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/ComparisonCategories.h" #include "llvm/ADT/APSInt.h" #include "llvm/Support/MathExtras.h" @@ -22,6 +23,7 @@ #include <cstdint> #include "Primitives.h" +#include "Program.h" namespace clang { namespace interp { @@ -69,7 +71,7 @@ template <unsigned Bits, bool Signed> class Integral final { // The primitive representing the integral. using ReprT = typename Repr<Bits, Signed>::Type; - ReprT V; + ReprT V = 0; static_assert(std::is_trivially_copyable_v<ReprT>); /// Primitive representing limits. @@ -83,7 +85,7 @@ template <unsigned Bits, bool Signed> class Integral final { using AsUnsigned = Integral<Bits, false>; /// Zero-initializes an integral. - Integral() : V(0) {} + Integral() = default; /// Constructs an integral from another integral. template <unsigned SrcBits, bool SrcSign> @@ -144,15 +146,12 @@ template <unsigned Bits, bool Signed> class Integral final { } constexpr static unsigned bitWidth() { return Bits; } + constexpr static bool isSigned() { return Signed; } + constexpr static bool isNumber() { return true; } bool isZero() const { return !V; } - bool isMin() const { return *this == min(bitWidth()); } - bool isMinusOne() const { return Signed && V == ReprT(-1); } - - constexpr static bool isSigned() { return Signed; } - bool isNegative() const { return V < ReprT(0); } bool isPositive() const { return !isNegative(); } @@ -205,7 +204,8 @@ template <unsigned Bits, bool Signed> class Integral final { static Integral zero(unsigned BitWidth = 0) { return from(0); } template <typename ValT> - static Integral from(ValT Value, unsigned NumBits = 0) { + static std::enable_if_t<!std::is_same_v<ValT, IntegralKind>, Integral> + from(ValT Value, unsigned NumBits = 0) { if constexpr (std::is_integral_v<ValT>) return Integral(Value); else @@ -213,7 +213,8 @@ template <unsigned Bits, bool Signed> class Integral final { } template <unsigned SrcBits, bool SrcSign> - static Integral from(Integral<SrcBits, SrcSign> Value) { + static std::enable_if_t<SrcBits != 0, Integral> + from(Integral<SrcBits, SrcSign> Value) { return Integral(Value.V); } @@ -287,7 +288,7 @@ template <unsigned Bits, bool Signed> class Integral final { *R = Integral::from(A.V >> B.V, OpBits); } -private: +public: template <typename T> static bool CheckAddUB(T A, T B, T &R) { if constexpr (std::is_signed_v<T>) { return llvm::AddOverflow<T>(A, B, R); @@ -327,6 +328,367 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Integral<Bits, Signed> I) { return OS; } +template <unsigned Bits, bool Signed> class IntegralOrPtr final { + static_assert(Bits >= 32); + +public: + // The primitive representing the integral. + using ReprT = typename Repr<Bits, Signed>::Type; + +private: + using OffsetT = intptr_t; + static_assert(std::is_trivially_copyable_v<ReprT>); + template <unsigned OtherBits, bool OtherSigned> friend class IntegralOrPtr; + + IntegralKind Kind = IntegralKind::Number; + union { + ReprT V; + struct { + const void *P; + OffsetT Offset; + } Ptr; + }; + + static_assert(sizeof(uintptr_t) >= sizeof(ReprT)); + + /// Primitive representing limits. + static const auto Min = std::numeric_limits<ReprT>::min(); + static const auto Max = std::numeric_limits<ReprT>::max(); + + /// Construct an integral from anything that is convertible to storage. + template <typename T> explicit IntegralOrPtr(T V) : V(V) {} + template <typename T> + explicit IntegralOrPtr(IntegralKind Kind, T V) : Kind(Kind), V(V) {} + +public: + using AsUnsigned = IntegralOrPtr<Bits, false>; + + /// Zero-initializes an integral. + IntegralOrPtr() = default; + + /// Constructs an integral from another integral. + template <unsigned SrcBits, bool SrcSign> + explicit IntegralOrPtr(Integral<SrcBits, SrcSign> V) : Kind(V.Kind), V(V) {} + + explicit IntegralOrPtr(IntegralKind Kind, const void *P, OffsetT Offset = 0) + : Kind(Kind) { + Ptr.P = P; + Ptr.Offset = Offset; + } + + explicit IntegralOrPtr(const void *P1, const void *P2) + : Kind(IntegralKind::AddrLabelDiff) { + Ptr.P = P1; + Ptr.Offset = reinterpret_cast<uintptr_t>(P2); + } + + IntegralKind getKind() const { return Kind; } + bool isNumber() const { return Kind == IntegralKind::Number; } + const void *getPtr() const { + assert(!isNumber()); + return Ptr.P; + } + ReprT getOffset() const { + assert(!isNumber()); + return Ptr.Offset; + } + + /// Construct an integral from a value based on signedness. + explicit IntegralOrPtr(const APSInt &V) + : V(V.isSigned() ? V.getSExtValue() : V.getZExtValue()) {} + + bool operator<(IntegralOrPtr RHS) const { return V < RHS.V; } + bool operator>(IntegralOrPtr RHS) const { return V > RHS.V; } + bool operator<=(IntegralOrPtr RHS) const { return V <= RHS.V; } + bool operator>=(IntegralOrPtr RHS) const { return V >= RHS.V; } + bool operator==(IntegralOrPtr RHS) const { return V == RHS.V; } + bool operator!=(IntegralOrPtr RHS) const { return V != RHS.V; } + bool operator>=(unsigned RHS) const { + return static_cast<unsigned>(V) >= RHS; + } + + bool operator>(unsigned RHS) const { + return V >= 0 && static_cast<unsigned>(V) > RHS; + } + + IntegralOrPtr operator-() const { return IntegralOrPtr(-V); } + IntegralOrPtr operator-(const IntegralOrPtr &Other) const { + return IntegralOrPtr(V - Other.V); + } + IntegralOrPtr operator~() const { return IntegralOrPtr(~V); } + + template <unsigned DstBits, bool DstSign> + explicit operator IntegralOrPtr<DstBits, DstSign>() const { + return IntegralOrPtr<DstBits, DstSign>(Kind, V); + } + + template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>> + explicit operator Ty() const { + return V; + } + + APSInt toAPSInt() const { + assert(isNumber()); + return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed); + } + + APSInt toAPSInt(unsigned BitWidth) const { + return APSInt(toAPInt(BitWidth), !Signed); + } + + APInt toAPInt(unsigned BitWidth) const { + assert(isNumber()); + if constexpr (Signed) + return APInt(Bits, static_cast<uint64_t>(V), Signed) + .sextOrTrunc(BitWidth); + else + return APInt(Bits, static_cast<uint64_t>(V), Signed) + .zextOrTrunc(BitWidth); + } + + APValue toAPValue(const ASTContext &) const { + switch (Kind) { + case IntegralKind::Address: { + return APValue((const ValueDecl *)Ptr.P, + CharUnits::fromQuantity(Ptr.Offset), + APValue::NoLValuePath{}); + } + case IntegralKind::LabelAddress: { + return APValue((const Expr *)Ptr.P, CharUnits::Zero(), + APValue::NoLValuePath{}); + } + case IntegralKind::BlockAddress: { + const Block *B = reinterpret_cast<const Block *>(Ptr.P); + const Descriptor *D = B->getDescriptor(); + if (const Expr *E = D->asExpr()) + return APValue(E, CharUnits::Zero(), APValue::NoLValuePath{}); + + return APValue(D->asValueDecl(), CharUnits::Zero(), + APValue::NoLValuePath{}); + } + case IntegralKind::AddrLabelDiff: { + return APValue( + (const AddrLabelExpr *)Ptr.P, + (const AddrLabelExpr *)reinterpret_cast<const void *>(Ptr.Offset)); + } + case IntegralKind::Number: + return APValue(toAPSInt()); + } + llvm_unreachable("Unhandled IntegralKind"); + } + + IntegralOrPtr<Bits, false> toUnsigned() const { + return IntegralOrPtr<Bits, false>(*this); + } + + constexpr static unsigned bitWidth() { return Bits; } + constexpr static bool isSigned() { return Signed; } + + bool isZero() const { return !V; } + bool isMin() const { return *this == min(bitWidth()); } + bool isMinusOne() const { return Signed && V == ReprT(-1); } + bool isNegative() const { return V < ReprT(0); } + bool isPositive() const { return !isNegative(); } + + ComparisonCategoryResult compare(const IntegralOrPtr &RHS) const { + return Compare(V, RHS.V); + } + + void bitcastToMemory(std::byte *Dest) const { + assert(isNumber()); + std::memcpy(Dest, &V, sizeof(V)); + } + + static IntegralOrPtr bitcastFromMemory(const std::byte *Src, + unsigned BitWidth) { + assert(BitWidth == sizeof(ReprT) * 8); + ReprT V; + + std::memcpy(&V, Src, sizeof(ReprT)); + return IntegralOrPtr(V); + } + + std::string toDiagnosticString(const ASTContext &Ctx) const { + std::string NameStr; + llvm::raw_string_ostream OS(NameStr); + OS << V; + return NameStr; + } + + unsigned countLeadingZeros() const { + assert(isNumber()); + if constexpr (!Signed) + return llvm::countl_zero<ReprT>(V); + if (isPositive()) + return llvm::countl_zero<typename AsUnsigned::ReprT>( + static_cast<typename AsUnsigned::ReprT>(V)); + llvm_unreachable("Don't call countLeadingZeros() on negative values."); + } + + IntegralOrPtr truncate(unsigned TruncBits) const { + assert(TruncBits >= 1); + if (TruncBits >= Bits) + return *this; + const ReprT BitMask = (ReprT(1) << ReprT(TruncBits)) - 1; + const ReprT SignBit = ReprT(1) << (TruncBits - 1); + const ReprT ExtMask = ~BitMask; + return IntegralOrPtr((V & BitMask) | + (Signed && (V & SignBit) ? ExtMask : 0)); + } + + void print(llvm::raw_ostream &OS) const { + switch (Kind) { + case IntegralKind::Number: + OS << V; + break; + case IntegralKind::AddrLabelDiff: + OS << Ptr.P << " - " << (const void *)Ptr.Offset << " (AddrLabelDiff)"; + break; + case IntegralKind::Address: + OS << Ptr.P << " + " << Ptr.Offset << " (Address)"; + break; + case IntegralKind::BlockAddress: + OS << Ptr.P << " + " << Ptr.Offset << " (BlockAddress)"; + break; + case IntegralKind::LabelAddress: + OS << Ptr.P << " + " << Ptr.Offset << " (LabelAddress)"; + } + } + + static IntegralOrPtr min(unsigned NumBits) { return IntegralOrPtr(Min); } + static IntegralOrPtr max(unsigned NumBits) { return IntegralOrPtr(Max); } + static IntegralOrPtr zero(unsigned BitWidth = 0) { return from(0); } + + template <typename ValT> + static std::enable_if_t<!std::is_same_v<ValT, IntegralKind>, IntegralOrPtr> + from(ValT V, unsigned NumBits = 0) { + if constexpr (std::is_integral_v<ValT>) + return IntegralOrPtr(V); + else + return IntegralOrPtr(static_cast<IntegralOrPtr::ReprT>(V)); + } + + template <unsigned SrcBits, bool SrcSign> + static std::enable_if_t<SrcBits != 0, IntegralOrPtr> + from(IntegralOrPtr<SrcBits, SrcSign> V) { + auto A = IntegralOrPtr(V.Kind, V.V); + switch (V.Kind) { + case IntegralKind::Number: + A.V = V.V; + break; + case IntegralKind::AddrLabelDiff: + case IntegralKind::Address: + case IntegralKind::BlockAddress: + case IntegralKind::LabelAddress: + A.Ptr.P = V.Ptr.P; + A.Ptr.Offset = V.Ptr.Offset; + break; + } + return A; + } + + template <typename T> static IntegralOrPtr from(IntegralKind Kind, T V) { + return IntegralOrPtr(Kind, V); + } + + static bool increment(IntegralOrPtr A, IntegralOrPtr *R) { + assert(A.isNumber()); + return add(A, IntegralOrPtr(ReprT(1)), A.bitWidth(), R); + } + + static bool decrement(IntegralOrPtr A, IntegralOrPtr *R) { + assert(A.isNumber()); + return sub(A, IntegralOrPtr(ReprT(1)), A.bitWidth(), R); + } + + static bool add(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits, + IntegralOrPtr *R) { + assert(A.isNumber() && B.isNumber()); + return Integral<Bits, Signed>::CheckAddUB(A.V, B.V, R->V); + } + + static bool sub(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits, + IntegralOrPtr *R) { + assert(A.isNumber() && B.isNumber()); + return Integral<Bits, Signed>::CheckSubUB(A.V, B.V, R->V); + } + + static bool mul(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits, + IntegralOrPtr *R) { + assert(A.isNumber() && B.isNumber()); + return Integral<Bits, Signed>::CheckMulUB(A.V, B.V, R->V); + } + + static bool rem(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits, + IntegralOrPtr *R) { + assert(A.isNumber() && B.isNumber()); + *R = IntegralOrPtr(A.V % B.V); + return false; + } + + static bool div(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits, + IntegralOrPtr *R) { + assert(A.isNumber() && B.isNumber()); + *R = IntegralOrPtr(A.V / B.V); + return false; + } + + static bool bitAnd(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits, + IntegralOrPtr *R) { + assert(A.isNumber() && B.isNumber()); + *R = IntegralOrPtr(A.V & B.V); + return false; + } + + static bool bitOr(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits, + IntegralOrPtr *R) { + assert(A.isNumber() && B.isNumber()); + *R = IntegralOrPtr(A.V | B.V); + return false; + } + + static bool bitXor(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits, + IntegralOrPtr *R) { + assert(A.isNumber() && B.isNumber()); + *R = IntegralOrPtr(A.V ^ B.V); + return false; + } + + static bool neg(IntegralOrPtr A, IntegralOrPtr *R) { + if (Signed && A.isMin()) + return true; + + *R = -A; + return false; + } + + static bool comp(IntegralOrPtr A, IntegralOrPtr *R) { + *R = IntegralOrPtr(~A.V); + return false; + } + + template <unsigned RHSBits, bool RHSSign> + static void shiftLeft(const IntegralOrPtr A, + const IntegralOrPtr<RHSBits, RHSSign> B, + unsigned OpBits, IntegralOrPtr *R) { + *R = IntegralOrPtr::from(A.V << B.V, OpBits); + } + + template <unsigned RHSBits, bool RHSSign> + static void shiftRight(const IntegralOrPtr A, + const IntegralOrPtr<RHSBits, RHSSign> B, + unsigned OpBits, IntegralOrPtr *R) { + *R = IntegralOrPtr::from(A.V >> B.V, OpBits); + } +}; + +template <unsigned Bits, bool Signed> +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + IntegralOrPtr<Bits, Signed> I) { + I.print(OS); + return OS; +} + } // namespace interp } // namespace clang diff --git a/clang/lib/AST/ByteCode/IntegralAP.h b/clang/lib/AST/ByteCode/IntegralAP.h index b11e6eea28e3f..9f53ac7716bba 100644 --- a/clang/lib/AST/ByteCode/IntegralAP.h +++ b/clang/lib/AST/ByteCode/IntegralAP.h @@ -139,6 +139,7 @@ template <bool Signed> class IntegralAP final { constexpr uint32_t bitWidth() const { return BitWidth; } constexpr unsigned numWords() const { return APInt::getNumWords(BitWidth); } constexpr bool singleWord() const { return numWords() == 1; } + constexpr static bool isNumber() { return true; } APSInt toAPSInt(unsigned Bits = 0) const { if (Bits == 0) diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index ebc7220aa5671..0f571f6789d10 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -88,20 +88,20 @@ static bool BCP(InterpState &S, CodePtr &RealPC, int32_t Offset, PrimType PT) { if (PT == PT_Ptr) { const auto &Ptr = S.Stk.pop<Pointer>(); assert(S.Stk.size() == StackSizeBefore); - S.Stk.push<Integral<32, true>>( - Integral<32, true>::from(CheckBCPResult(S, Ptr))); + S.Stk.push<IntegralOrPtr<32, true>>( + IntegralOrPtr<32, true>::from(CheckBCPResult(S, Ptr))); } else { // Pop the result from the stack and return success. TYPE_SWITCH(PT, S.Stk.pop<T>();); assert(S.Stk.size() == StackSizeBefore); - S.Stk.push<Integral<32, true>>(Integral<32, true>::from(1)); + S.Stk.push<IntegralOrPtr<32, true>>(IntegralOrPtr<32, true>::from(1)); } } else { if (!S.inConstantContext()) return Invalid(S, RealPC); S.Stk.clearTo(StackSizeBefore); - S.Stk.push<Integral<32, true>>(Integral<32, true>::from(0)); + S.Stk.push<IntegralOrPtr<32, true>>(IntegralOrPtr<32, true>::from(0)); } // RealPC should not have been modified. @@ -2187,12 +2187,15 @@ bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, S.CCEDiag(E, diag::note_constexpr_invalid_cast) << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); - if (Ptr.isDummy()) + if (S.getLangOpts().CPlusPlus && Ptr.isDummy() && !Ptr.pointsToLabel()) return false; - if (Ptr.isFunctionPointer()) + if (Ptr.isIntegralPointer()) + return true; + + if (Ptr.isDummy()) return true; - if (Ptr.isBlockPointer() && !Ptr.isZero()) { + if (!Ptr.isZero()) { // Only allow based lvalue casts if they are lossless. if (S.getASTContext().getTargetInfo().getPointerWidth(LangAS::Default) != BitWidth) @@ -2201,6 +2204,11 @@ bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, return true; } +bool CheckIntegralAddressCast(InterpState &S, CodePtr OpPC, unsigned BitWidth) { + return (S.getASTContext().getTargetInfo().getPointerWidth(LangAS::Default) == + BitWidth); +} + bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) { const Pointer &Ptr = S.Stk.pop<Pointer>(); @@ -2286,13 +2294,19 @@ bool DiagTypeid(InterpState &S, CodePtr OpPC) { bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, const Pointer &RHS) { + if (!LHS.pointsToStr... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/185028 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
