tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }