summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--clang/lib/Sema/SemaDecl.cpp49
-rw-r--r--clang/test/CXX/class.derived/class.abstract/p16.cpp16
3 files changed, 60 insertions, 11 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8389e4e10fa..3c420b9d2b6 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4161078d656..6791273384f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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);
}
}
}
diff --git a/clang/test/CXX/class.derived/class.abstract/p16.cpp b/clang/test/CXX/class.derived/class.abstract/p16.cpp
new file mode 100644
index 00000000000..93f905cd33b
--- /dev/null
+++ b/clang/test/CXX/class.derived/class.abstract/p16.cpp
@@ -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;
+};
OpenPOWER on IntegriCloud