diff options
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
| -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; |

