diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 30 | ||||
-rw-r--r-- | test/SemaCXX/virtual-override.cpp | 12 |
4 files changed, 39 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index bff8c054f1..ef6d05b505 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -608,6 +608,8 @@ def err_virtual_non_function : Error< "'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 d9057a1e0d..b1cd5628a7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -712,7 +712,7 @@ public: 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 10785270e5..6f0a7da450 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3153,23 +3153,28 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, /// 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 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, 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 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // 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 b1d2a3a05c..ba2b80dacd 100644 --- a/test/SemaCXX/virtual-override.cpp +++ b/test/SemaCXX/virtual-override.cpp @@ -276,3 +276,15 @@ namespace T12 { 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}} + }; +} |