Commit 29dc0b17 authored by Aaron Ballman's avatar Aaron Ballman
Browse files

Add the readability-redundant-access-specifiers check.

This finds redundant access specifier declarations inside classes, structs, and unions.

Patch by Mateusz Mackowski.
parent e5972f2a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ add_clang_library(clangTidyReadabilityModule
  NamespaceCommentCheck.cpp
  NonConstParameterCheck.cpp
  ReadabilityTidyModule.cpp
  RedundantAccessSpecifiersCheck.cpp
  RedundantControlFlowCheck.cpp
  RedundantDeclarationCheck.cpp
  RedundantFunctionPtrDereferenceCheck.cpp
+3 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "MisplacedArrayIndexCheck.h"
#include "NamedParameterCheck.h"
#include "NonConstParameterCheck.h"
#include "RedundantAccessSpecifiersCheck.h"
#include "RedundantControlFlowCheck.h"
#include "RedundantDeclarationCheck.h"
#include "RedundantFunctionPtrDereferenceCheck.h"
@@ -82,6 +83,8 @@ public:
        "readability-misleading-indentation");
    CheckFactories.registerCheck<MisplacedArrayIndexCheck>(
        "readability-misplaced-array-index");
    CheckFactories.registerCheck<RedundantAccessSpecifiersCheck>(
        "readability-redundant-access-specifiers");
    CheckFactories.registerCheck<RedundantFunctionPtrDereferenceCheck>(
        "readability-redundant-function-ptr-dereference");
    CheckFactories.registerCheck<RedundantMemberInitCheck>(
+85 −0
Original line number Diff line number Diff line
//===--- RedundantAccessSpecifiersCheck.cpp - clang-tidy ------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "RedundantAccessSpecifiersCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace readability {

void RedundantAccessSpecifiersCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(
      cxxRecordDecl(has(accessSpecDecl())).bind("redundant-access-specifiers"),
      this);
}

void RedundantAccessSpecifiersCheck::check(
    const MatchFinder::MatchResult &Result) {
  const auto *MatchedDecl =
      Result.Nodes.getNodeAs<CXXRecordDecl>("redundant-access-specifiers");

  const AccessSpecDecl *LastASDecl = nullptr;
  for (DeclContext::specific_decl_iterator<AccessSpecDecl>
           AS(MatchedDecl->decls_begin()),
       ASEnd(MatchedDecl->decls_end());
       AS != ASEnd; ++AS) {
    const AccessSpecDecl *ASDecl = *AS;

    // Ignore macro expansions.
    if (ASDecl->getLocation().isMacroID()) {
      LastASDecl = ASDecl;
      continue;
    }

    if (LastASDecl == nullptr) {
      // First declaration.
      LastASDecl = ASDecl;

      if (CheckFirstDeclaration) {
        AccessSpecifier DefaultSpecifier =
            MatchedDecl->isClass() ? AS_private : AS_public;
        if (ASDecl->getAccess() == DefaultSpecifier) {
          diag(ASDecl->getLocation(),
               "redundant access specifier has the same accessibility as the "
               "implicit access specifier")
              << FixItHint::CreateRemoval(ASDecl->getSourceRange());
        }
      }

      continue;
    }

    if (LastASDecl->getAccess() == ASDecl->getAccess()) {
      // Ignore macro expansions.
      if (LastASDecl->getLocation().isMacroID()) {
        LastASDecl = ASDecl;
        continue;
      }

      diag(ASDecl->getLocation(),
           "redundant access specifier has the same accessibility as the "
           "previous access specifier")
          << FixItHint::CreateRemoval(ASDecl->getSourceRange());
      diag(LastASDecl->getLocation(), "previously declared here",
           DiagnosticIDs::Note);
    } else {
      LastASDecl = ASDecl;
    }
  }
}

} // namespace readability
} // namespace tidy
} // namespace clang
+39 −0
Original line number Diff line number Diff line
//===--- RedundantAccessSpecifiersCheck.h - clang-tidy ----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTACCESSSPECIFIERSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTACCESSSPECIFIERSCHECK_H

#include "../ClangTidyCheck.h"

namespace clang {
namespace tidy {
namespace readability {

/// Detects redundant access specifiers inside classes, structs, and unions.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-access-specifiers.html
class RedundantAccessSpecifiersCheck : public ClangTidyCheck {
public:
  RedundantAccessSpecifiersCheck(StringRef Name, ClangTidyContext *Context)
      : ClangTidyCheck(Name, Context),
        CheckFirstDeclaration(
            Options.getLocalOrGlobal("CheckFirstDeclaration", false)) {}
  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

private:
  const bool CheckFirstDeclaration;
};

} // namespace readability
} // namespace tidy
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTACCESSSPECIFIERSCHECK_H
+6 −0
Original line number Diff line number Diff line
@@ -135,6 +135,12 @@ Improvements to include-fixer

The improvements are...

- New :doc:`readability-redundant-access-specifiers
  <clang-tidy/checks/readability-redundant-access-specifiers>` check.

  Finds classes, structs, and unions that contain redundant member
  access specifiers.

Improvements to clang-include-fixer
-----------------------------------

Loading