forked from OSchip/llvm-project
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:
parent
5c1ac4ea72
commit
7e414261f6
|
@ -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">,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
Loading…
Reference in New Issue