Author: Timm Baeder Date: 2024-10-31T10:13:40+01:00 New Revision: f0b9a0ba0649e11f190d20e86f92b566dfb8da0f
URL: https://github.com/llvm/llvm-project/commit/f0b9a0ba0649e11f190d20e86f92b566dfb8da0f DIFF: https://github.com/llvm/llvm-project/commit/f0b9a0ba0649e11f190d20e86f92b566dfb8da0f.diff LOG: [clang][bytecode] Diagnose delete with non-virtual dtor (#114373) ... in the base class. Added: Modified: clang/lib/AST/ByteCode/Interp.cpp clang/test/AST/ByteCode/new-delete.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 513d4512b45cff..3094d7986f9986 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1002,6 +1002,13 @@ static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) { return runRecordDestructor(S, OpPC, Pointer(const_cast<Block *>(B)), Desc); } +static bool hasVirtualDestructor(QualType T) { + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + if (const CXXDestructorDecl *DD = RD->getDestructor()) + return DD->isVirtual(); + return false; +} + bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete) { if (!CheckDynamicMemoryAllocation(S, OpPC)) @@ -1019,9 +1026,20 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, return true; // Remove base casts. + QualType InitialType = Ptr.getType(); while (Ptr.isBaseClass()) Ptr = Ptr.getBase(); + // For the non-array case, the types must match if the static type + // does not have a virtual destructor. + if (!DeleteIsArrayForm && Ptr.getType() != InitialType && + !hasVirtualDestructor(InitialType)) { + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_delete_base_nonvirt_dtor) + << InitialType << Ptr.getType(); + return false; + } + if (!Ptr.isRoot() || Ptr.isOnePastEnd() || Ptr.isArrayElement()) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_delete_subobject) diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index 94fe2d4497df6a..31c8da93a3a643 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -569,6 +569,16 @@ namespace CastedDelete { return a; } static_assert(vdtor_1() == 1); + + constexpr int foo() { // both-error {{never produces a constant expression}} + struct S {}; + struct T : S {}; + S *p = new T(); + delete p; // both-note 2{{delete of object with dynamic type 'T' through pointer to base class type 'S' with non-virtual destructor}} + return 1; + } + static_assert(foo() == 1); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} } constexpr void use_after_free_2() { // both-error {{never produces a constant expression}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits