MustOverrideChecker.cpp (2273B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "MustOverrideChecker.h" 6 #include "CustomMatchers.h" 7 8 void MustOverrideChecker::registerMatchers(MatchFinder *AstMatcher) { 9 AstMatcher->addMatcher(cxxRecordDecl(isDefinition()).bind("class"), this); 10 } 11 12 void MustOverrideChecker::registerPPCallbacks(CompilerInstance &CI) { 13 this->CI = &CI; 14 } 15 16 void MustOverrideChecker::check(const MatchFinder::MatchResult &Result) { 17 auto D = Result.Nodes.getNodeAs<CXXRecordDecl>("class"); 18 19 // Look through all of our immediate bases to find methods that need to be 20 // overridden 21 typedef std::vector<CXXMethodDecl *> OverridesVector; 22 OverridesVector MustOverrides; 23 for (const auto &Base : D->bases()) { 24 // The base is either a class (CXXRecordDecl) or it's a templated class... 25 CXXRecordDecl *Parent = Base.getType() 26 .getDesugaredType(D->getASTContext()) 27 ->getAsCXXRecordDecl(); 28 // The parent might not be resolved to a type yet. In this case, we can't 29 // do any checking here. For complete correctness, we should visit 30 // template instantiations, but this case is likely to be rare, so we will 31 // ignore it until it becomes important. 32 if (!Parent) { 33 continue; 34 } 35 Parent = Parent->getDefinition(); 36 for (const auto &M : Parent->methods()) { 37 if (hasCustomAttribute<moz_must_override>(M)) 38 MustOverrides.push_back(M); 39 } 40 } 41 42 for (auto &O : MustOverrides) { 43 bool Overridden = false; 44 for (const auto &M : D->methods()) { 45 // The way that Clang checks if a method M overrides its parent method 46 // is if the method has the same name but would not overload. 47 if (getNameChecked(M) == getNameChecked(O) && 48 !CI->getSema().IsOverload(M, O, false)) { 49 Overridden = true; 50 break; 51 } 52 } 53 if (!Overridden) { 54 diag(D->getLocation(), "%0 must override %1", DiagnosticIDs::Error) 55 << D->getDeclName() << O->getDeclName(); 56 diag(O->getLocation(), "function to override is here", 57 DiagnosticIDs::Note); 58 } 59 } 60 }