llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> If the target type is a pointer type. --- Full diff: https://github.com/llvm/llvm-project/pull/127615.diff 5 Files Affected: - (modified) clang/lib/AST/ByteCode/Compiler.cpp (+4-2) - (modified) clang/lib/AST/ByteCode/Interp.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/Interp.h (+15-4) - (modified) clang/lib/AST/ByteCode/Opcodes.td (+2-4) - (modified) clang/test/AST/ByteCode/records.cpp (+17-1) ``````````diff diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 59c236c9da8c8..c58e884c77d6b 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -272,7 +272,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { CurType = B->getType(); } else { unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType); - if (!this->emitGetPtrBasePop(DerivedOffset, CE)) + if (!this->emitGetPtrBasePop( + DerivedOffset, /*NullOK=*/CE->getType()->isPointerType(), CE)) return false; CurType = B->getType(); } @@ -288,7 +289,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { unsigned DerivedOffset = collectBaseOffset(SubExpr->getType(), CE->getType()); - return this->emitGetPtrDerivedPop(DerivedOffset, CE); + return this->emitGetPtrDerivedPop( + DerivedOffset, /*NullOK=*/CE->getType()->isPointerType(), CE); } case CK_FloatingCast: { diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index c80be094856b0..f09081101f086 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1432,7 +1432,7 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, unsigned Offset = S.getContext().collectBaseOffset( InitialPointeeType->getAsRecordDecl(), OverriderPointeeType->getAsRecordDecl()); - return GetPtrBasePop(S, OpPC, Offset); + return GetPtrBasePop(S, OpPC, Offset, /*IsNullOK=*/true); } return true; diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 73cc107b7dbff..0f24c83d03029 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1568,10 +1568,20 @@ inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) { return true; } -inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) { +inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off, + bool NullOK) { const Pointer &Ptr = S.Stk.pop<Pointer>(); - if (!CheckNull(S, OpPC, Ptr, CSK_Derived)) + if (!NullOK && !CheckNull(S, OpPC, Ptr, CSK_Derived)) return false; + + if (!Ptr.isBlockPointer()) { + // FIXME: We don't have the necessary information in integral pointers. + // The Descriptor only has a record, but that does of course not include + // the potential derived classes of said record. + S.Stk.push<Pointer>(Ptr); + return true; + } + if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived)) return false; if (!CheckDowncast(S, OpPC, Ptr, Off)) @@ -1600,10 +1610,11 @@ inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) { return true; } -inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) { +inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off, + bool NullOK) { const Pointer &Ptr = S.Stk.pop<Pointer>(); - if (!CheckNull(S, OpPC, Ptr, CSK_Base)) + if (!NullOK && !CheckNull(S, OpPC, Ptr, CSK_Base)) return false; if (!Ptr.isBlockPointer()) { diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 088a3e40fe2a7..41e4bae65c195 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -312,7 +312,7 @@ def GetPtrThisField : OffsetOpcode; // [Pointer] -> [Pointer] def GetPtrBase : OffsetOpcode; // [Pointer] -> [Pointer] -def GetPtrBasePop : OffsetOpcode; +def GetPtrBasePop : OffsetOpcode { let Args = [ArgUint32, ArgBool]; } def GetMemberPtrBasePop : Opcode { // Offset of field, which is a base. let Args = [ArgSint32]; @@ -322,9 +322,7 @@ def GetMemberPtrBasePop : Opcode { def FinishInitPop : Opcode; def FinishInit : Opcode; -def GetPtrDerivedPop : Opcode { - let Args = [ArgUint32]; -} +def GetPtrDerivedPop : Opcode { let Args = [ArgUint32, ArgBool]; } // [Pointer] -> [Pointer] def GetPtrVirtBasePop : Opcode { diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp index 9470e7d8e3dcb..3cc3210841e0f 100644 --- a/clang/test/AST/ByteCode/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -1656,12 +1656,28 @@ namespace ExprWithCleanups { static_assert(F == 1i, ""); } -namespace NullptrUpcast { +namespace NullptrCast { struct A {}; struct B : A { int n; }; + constexpr A *na = nullptr; constexpr B *nb = nullptr; constexpr A &ra = *nb; // both-error {{constant expression}} \ // both-note {{cannot access base class of null pointer}} + constexpr B &rb = (B&)*na; // both-error {{constant expression}} \ + // both-note {{cannot access derived class of null pointer}} + constexpr bool test() { + auto a = (A*)(B*)nullptr; + + return a == nullptr; + } + static_assert(test(), ""); + + constexpr bool test2() { + auto a = (B*)(A*)nullptr; + + return a == nullptr; + } + static_assert(test2(), ""); } namespace NonConst { `````````` </details> https://github.com/llvm/llvm-project/pull/127615 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits