Implement C++ 10.3p16 - overrides involving deleted functions must match.

Only deleted functions may override deleted functions and non-deleted functions
may only override non-deleted functions.

llvm-svn: 166082
This commit is contained in:
David Blaikie 2012-10-17 00:47:58 +00:00
parent 5c1ac4ea72
commit 7e414261f6
3 changed files with 60 additions and 11 deletions

View File

@ -865,6 +865,12 @@ def note_pure_virtual_function : Note<
def err_deleted_decl_not_first : Error<
"deleted definition must be first declaration">;
def err_deleted_override : Error<
"deleted function %0 cannot override a non-deleted function">;
def err_non_deleted_override : Error<
"non-deleted function %0 cannot override a deleted function">;
def warn_weak_vtable : Warning<
"%0 has no out-of-line virtual method definitions; its vtable will be "
"emitted in every translation unit">,

View File

@ -4733,6 +4733,31 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
return false;
}
namespace {
enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
}
/// \brief Report an error regarding overriding, along with any relevant
/// overriden methods.
///
/// \param DiagID the primary error to report.
/// \param MD the overriding method.
/// \param OEK which overrides to include as notes.
static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD,
OverrideErrorKind OEK = OEK_All) {
S.Diag(MD->getLocation(), DiagID) << MD->getDeclName();
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods();
I != E; ++I) {
// This check (& the OEK parameter) could be replaced by a predicate, but
// without lambdas that would be overkill. This is still nicer than writing
// out the diag loop 3 times.
if ((OEK == OEK_All) ||
(OEK == OEK_NonDeleted && !(*I)->isDeleted()) ||
(OEK == OEK_Deleted && (*I)->isDeleted()))
S.Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
}
}
/// AddOverriddenMethods - See if a method overrides any in the base classes,
/// and if so, check that it's a valid override and remember it.
bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
@ -4741,6 +4766,8 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
FindOverriddenMethodData Data;
Data.Method = MD;
Data.S = this;
bool hasDeletedOverridenMethods = false;
bool hasNonDeletedOverridenMethods = false;
bool AddedAny = false;
if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
@ -4750,12 +4777,21 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
!CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
!CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
hasDeletedOverridenMethods |= OldMD->isDeleted();
hasNonDeletedOverridenMethods |= !OldMD->isDeleted();
AddedAny = true;
}
}
}
}
if (hasDeletedOverridenMethods && !MD->isDeleted()) {
ReportOverrides(*this, diag::err_non_deleted_override, MD, OEK_Deleted);
}
if (hasNonDeletedOverridenMethods && MD->isDeleted()) {
ReportOverrides(*this, diag::err_deleted_override, MD, OEK_NonDeleted);
}
return AddedAny;
}
@ -6068,16 +6104,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (AddOverriddenMethods(Method->getParent(), Method)) {
// If the function was marked as "static", we have a problem.
if (NewFD->getStorageClass() == SC_Static) {
Diag(NewFD->getLocation(), diag::err_static_overrides_virtual)
<< NewFD->getDeclName();
for (CXXMethodDecl::method_iterator
Overridden = Method->begin_overridden_methods(),
OverriddenEnd = Method->end_overridden_methods();
Overridden != OverriddenEnd;
++Overridden) {
Diag((*Overridden)->getLocation(),
diag::note_overridden_virtual_function);
}
ReportOverrides(*this, diag::err_static_overrides_virtual, Method);
}
}
}

View File

@ -0,0 +1,16 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
struct A {
virtual void a(); // expected-note{{overridden virtual function is here}}
virtual void b() = delete; // expected-note{{overridden virtual function is here}}
};
struct B: A {
virtual void a() = delete; // expected-error{{deleted function 'a' cannot override a non-deleted function}}
virtual void b(); // expected-error{{non-deleted function 'b' cannot override a deleted function}}
};
struct C: A {
virtual void a();
virtual void b() = delete;
};