summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp14
1 files changed, 13 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index a3e3c11c6ad..86a4ecc1fc5 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1913,6 +1913,18 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
DiagnoseUseOfDecl(Dtor, StartLoc);
}
+ // Deleting an abstract class with a non-virtual destructor is always
+ // undefined per [expr.delete]p3, and leads to strange-looking
+ // linker errors.
+ if (PointeeRD->isAbstract()) {
+ CXXDestructorDecl *dtor = PointeeRD->getDestructor();
+ if (dtor && !dtor->isVirtual()) {
+ Diag(StartLoc, diag::err_delete_abstract_non_virtual_dtor)
+ << PointeeElem;
+ return ExprError();
+ }
+ }
+
// C++ [expr.delete]p3:
// In the first alternative (delete object), if the static type of the
// object to be deleted is different from its dynamic type, the static
@@ -1924,7 +1936,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (!ArrayForm && PointeeRD->isPolymorphic() &&
!PointeeRD->hasAttr<FinalAttr>()) {
CXXDestructorDecl *dtor = PointeeRD->getDestructor();
- if (!dtor || !dtor->isVirtual())
+ if (dtor && !dtor->isVirtual())
Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem;
}
OpenPOWER on IntegriCloud