diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-10-07 03:14:28 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-10-07 03:14:28 +0000 |
| commit | df3761f6dcdac76efcdcdc85d4011f0e716e8baa (patch) | |
| tree | 00a20d6e012a5466366f16a5e543d25488771d41 /clang/lib/AST | |
| parent | 74ce7112c3fccccfa7edb134c0a2d8fe2aab462f (diff) | |
| download | bcm5719-llvm-df3761f6dcdac76efcdcdc85d4011f0e716e8baa.tar.gz bcm5719-llvm-df3761f6dcdac76efcdcdc85d4011f0e716e8baa.zip | |
[c++20] Check for a class-specific operator delete when deleting an
object of class type with a virtual destructor.
llvm-svn: 373875
Diffstat (limited to 'clang/lib/AST')
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 8c56a3cc550..c32f516aec7 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -6019,6 +6019,13 @@ static bool hasVirtualDestructor(QualType T) { return false; } +static const FunctionDecl *getVirtualOperatorDelete(QualType T) { + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + if (CXXDestructorDecl *DD = RD->getDestructor()) + return DD->isVirtual() ? DD->getOperatorDelete() : nullptr; + return nullptr; +} + /// Check that the given object is a suitable pointer to a heap allocation that /// still exists and is of the right kind for the purpose of a deletion. /// @@ -13208,6 +13215,18 @@ bool VoidExprEvaluator::VisitCXXDeleteExpr(const CXXDeleteExpr *E) { return false; } + // For a class type with a virtual destructor, the selected operator delete + // is the one looked up when building the destructor. + if (!E->isArrayForm() && !E->isGlobalDelete()) { + const FunctionDecl *VirtualDelete = getVirtualOperatorDelete(AllocType); + if (VirtualDelete && + !VirtualDelete->isReplaceableGlobalAllocationFunction()) { + Info.FFDiag(E, diag::note_constexpr_new_non_replaceable) + << isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete; + return false; + } + } + if (!HandleDestruction(Info, E->getExprLoc(), Pointer.getLValueBase(), (*Alloc)->Value, AllocType)) return false; |

