tor-browser

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

NoDuplicateRefCntMemberChecker.cpp (2627B)


      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 "NoDuplicateRefCntMemberChecker.h"
      6 #include "CustomMatchers.h"
      7 
      8 void NoDuplicateRefCntMemberChecker::registerMatchers(MatchFinder *AstMatcher) {
      9  AstMatcher->addMatcher(cxxRecordDecl().bind("decl"), this);
     10 }
     11 
     12 void NoDuplicateRefCntMemberChecker::check(
     13    const MatchFinder::MatchResult &Result) {
     14  const CXXRecordDecl *D = Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
     15  const FieldDecl *RefCntMember = getClassRefCntMember(D);
     16  const FieldDecl *FoundRefCntBase = nullptr;
     17 
     18  if (!D->hasDefinition())
     19    return;
     20  D = D->getDefinition();
     21 
     22  // If we don't have an mRefCnt member, and we have less than 2 superclasses,
     23  // we don't have to run this loop, as neither case will ever apply.
     24  if (!RefCntMember && D->getNumBases() < 2) {
     25    return;
     26  }
     27 
     28  // Check every superclass for whether it has a base with a refcnt member, and
     29  // warn for those which do
     30  for (auto &Base : D->bases()) {
     31    // Determine if this base class has an mRefCnt member
     32    const FieldDecl *BaseRefCntMember = getBaseRefCntMember(Base.getType());
     33 
     34    if (BaseRefCntMember) {
     35      if (RefCntMember) {
     36        // We have an mRefCnt, and superclass has an mRefCnt
     37        const char *Error = "Refcounted record %0 has multiple mRefCnt members";
     38        const char *Note1 = "Superclass %0 also has an mRefCnt member";
     39        const char *Note2 =
     40            "Consider using the _INHERITED macros for AddRef and Release here";
     41 
     42        diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << D;
     43        diag(BaseRefCntMember->getBeginLoc(), Note1, DiagnosticIDs::Note)
     44            << BaseRefCntMember->getParent();
     45        diag(RefCntMember->getBeginLoc(), Note2, DiagnosticIDs::Note);
     46      }
     47 
     48      if (FoundRefCntBase) {
     49        const char *Error = "Refcounted record %0 has multiple superclasses "
     50                            "with mRefCnt members";
     51        const char *Note = "Superclass %0 has an mRefCnt member";
     52 
     53        // superclass has mRefCnt, and another superclass also has an mRefCnt
     54        diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << D;
     55        diag(BaseRefCntMember->getBeginLoc(), Note, DiagnosticIDs::Note)
     56            << BaseRefCntMember->getParent();
     57        diag(FoundRefCntBase->getBeginLoc(), Note, DiagnosticIDs::Note)
     58            << FoundRefCntBase->getParent();
     59      }
     60 
     61      // Record that we've found a base with a mRefCnt member
     62      FoundRefCntBase = BaseRefCntMember;
     63    }
     64  }
     65 }