summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-10-07 03:14:28 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-10-07 03:14:28 +0000
commitdf3761f6dcdac76efcdcdc85d4011f0e716e8baa (patch)
tree00a20d6e012a5466366f16a5e543d25488771d41 /clang/lib/AST
parent74ce7112c3fccccfa7edb134c0a2d8fe2aab462f (diff)
downloadbcm5719-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.cpp19
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;
OpenPOWER on IntegriCloud