Diagnose when a 'static' member function overrides a virtual function
in a base class. Fixes PR8168.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116448 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index bff8c05..ef6d05b 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -608,6 +608,8 @@
"'virtual' can only appear on non-static member functions">;
def err_virtual_out_of_class : Error<
"'virtual' can only be specified inside the class definition">;
+def err_static_overrides_virtual : Error<
+ "'static' member function %0 overrides a virtual function in a base class">;
def err_explicit_non_function : Error<
"'explicit' can only appear on non-static member functions">;
def err_explicit_out_of_class : Error<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index d9057a1..b1cd562 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -712,7 +712,7 @@
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition,
bool &Redeclaration);
- void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+ bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
void CheckFunctionDeclaration(Scope *S,
FunctionDecl *NewFD, LookupResult &Previous,
bool IsExplicitSpecialization,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1078527..6f0a7da 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3153,23 +3153,28 @@
/// AddOverriddenMethods - See if a method overrides any in the base classes,
/// and if so, check that it's a valid override and remember it.
-void Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
// Look for virtual methods in base classes that this method might override.
CXXBasePaths Paths;
FindOverriddenMethodData Data;
Data.Method = MD;
Data.S = this;
+ bool AddedAny = false;
if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
E = Paths.found_decls_end(); I != E; ++I) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
!CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
- !CheckOverridingFunctionAttributes(MD, OldMD))
+ !CheckOverridingFunctionAttributes(MD, OldMD)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
+ AddedAny = true;
+ }
}
}
}
+
+ return AddedAny;
}
static void DiagnoseInvalidRedeclaration(Sema &S, FunctionDecl *NewFD) {
@@ -3964,8 +3969,6 @@
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(ClassType));
-// NewFD->getDeclName().dump();
-// Name.dump();
if (NewFD->getDeclName() != Name) {
Diag(NewFD->getLocation(), diag::err_destructor_name);
return NewFD->setInvalidDecl();
@@ -3979,8 +3982,23 @@
// Find any virtual functions that this function overrides.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD)) {
if (!Method->isFunctionTemplateSpecialization() &&
- !Method->getDescribedFunctionTemplate())
- AddOverriddenMethods(Method->getParent(), Method);
+ !Method->getDescribedFunctionTemplate()) {
+ 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);
+ }
+ }
+ }
+ }
}
// Extra checking for C++ overloaded operators (C++ [over.oper]).
diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp
index b1d2a3a..ba2b80d 100644
--- a/test/SemaCXX/virtual-override.cpp
+++ b/test/SemaCXX/virtual-override.cpp
@@ -276,3 +276,15 @@
virtual B& f(); // expected-error {{virtual function 'f' has a different return type ('T12::B &') than the function it overrides (which has return type 'T12::A &&')}}
};
};
+
+namespace PR8168 {
+ class A {
+ public:
+ virtual void foo() {} // expected-note{{overridden virtual function is here}}
+ };
+
+ class B : public A {
+ public:
+ static void foo() {} // expected-error{{'static' member function 'foo' overrides a virtual function}}
+ };
+}