forked from OSchip/llvm-project
Re-fix r136172 so it isn't an error; apparently, some people are fond of their undefined behavior.
llvm-svn: 136183
This commit is contained in:
parent
8f95f425aa
commit
1b71a22b28
|
@ -3421,8 +3421,9 @@ def warn_non_virtual_dtor : Warning<
|
|||
def warn_delete_non_virtual_dtor : Warning<
|
||||
"delete called on %0 that has virtual functions but non-virtual destructor">,
|
||||
InGroup<DeleteNonVirtualDtor>, DefaultIgnore;
|
||||
def err_delete_abstract_non_virtual_dtor : Error<
|
||||
"cannot delete %0, which is abstract and does not have a virtual destructor">;
|
||||
def warn_delete_abstract_non_virtual_dtor : Warning<
|
||||
"delete called on %0 that is abstract but has non-virtual destructor">,
|
||||
InGroup<DeleteNonVirtualDtor>;
|
||||
def warn_overloaded_virtual : Warning<
|
||||
"%q0 hides overloaded virtual %select{function|functions}1">,
|
||||
InGroup<OverloadedVirtual>, DefaultIgnore;
|
||||
|
|
|
@ -1913,18 +1913,6 @@ 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
|
||||
|
@ -1933,11 +1921,20 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
|
|||
// behavior is undefined.
|
||||
//
|
||||
// Note: a final class cannot be derived from, no issue there
|
||||
if (!ArrayForm && PointeeRD->isPolymorphic() &&
|
||||
!PointeeRD->hasAttr<FinalAttr>()) {
|
||||
if (PointeeRD->isPolymorphic() && !PointeeRD->hasAttr<FinalAttr>()) {
|
||||
CXXDestructorDecl *dtor = PointeeRD->getDestructor();
|
||||
if (dtor && !dtor->isVirtual())
|
||||
Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem;
|
||||
if (dtor && !dtor->isVirtual()) {
|
||||
if (PointeeRD->isAbstract()) {
|
||||
// If the class is abstract, we warn by default, because we're
|
||||
// sure the code has undefined behavior.
|
||||
Diag(StartLoc, diag::warn_delete_abstract_non_virtual_dtor)
|
||||
<< PointeeElem;
|
||||
} else if (!ArrayForm) {
|
||||
// Otherwise, if this is not an array delete, it's a bit suspect,
|
||||
// but not necessarily wrong.
|
||||
Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (getLangOptions().ObjCAutoRefCount &&
|
||||
|
|
|
@ -414,5 +414,5 @@ namespace PR10504 {
|
|||
struct A {
|
||||
virtual void foo() = 0;
|
||||
};
|
||||
void f(A *x) { delete x; } // expected-error {{cannot delete 'PR10504::A', which is abstract and does not have a virtual destructor}}
|
||||
void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue