clang-tools  10.0.0
RedundantAccessSpecifiersCheck.cpp
Go to the documentation of this file.
1 //===--- RedundantAccessSpecifiersCheck.cpp - clang-tidy ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 
13 using namespace clang::ast_matchers;
14 
15 namespace clang {
16 namespace tidy {
17 namespace readability {
18 
19 void RedundantAccessSpecifiersCheck::registerMatchers(MatchFinder *Finder) {
20  if (!getLangOpts().CPlusPlus)
21  return;
22 
23  Finder->addMatcher(
24  cxxRecordDecl(has(accessSpecDecl())).bind("redundant-access-specifiers"),
25  this);
26 }
27 
28 void RedundantAccessSpecifiersCheck::check(
29  const MatchFinder::MatchResult &Result) {
30  const auto *MatchedDecl =
31  Result.Nodes.getNodeAs<CXXRecordDecl>("redundant-access-specifiers");
32 
33  const AccessSpecDecl *LastASDecl = nullptr;
34  for (DeclContext::specific_decl_iterator<AccessSpecDecl>
35  AS(MatchedDecl->decls_begin()),
36  ASEnd(MatchedDecl->decls_end());
37  AS != ASEnd; ++AS) {
38  const AccessSpecDecl *ASDecl = *AS;
39 
40  // Ignore macro expansions.
41  if (ASDecl->getLocation().isMacroID()) {
42  LastASDecl = ASDecl;
43  continue;
44  }
45 
46  if (LastASDecl == nullptr) {
47  // First declaration.
48  LastASDecl = ASDecl;
49 
50  if (CheckFirstDeclaration) {
51  AccessSpecifier DefaultSpecifier =
52  MatchedDecl->isClass() ? AS_private : AS_public;
53  if (ASDecl->getAccess() == DefaultSpecifier) {
54  diag(ASDecl->getLocation(),
55  "redundant access specifier has the same accessibility as the "
56  "implicit access specifier")
57  << FixItHint::CreateRemoval(ASDecl->getSourceRange());
58  }
59  }
60 
61  continue;
62  }
63 
64  if (LastASDecl->getAccess() == ASDecl->getAccess()) {
65  // Ignore macro expansions.
66  if (LastASDecl->getLocation().isMacroID()) {
67  LastASDecl = ASDecl;
68  continue;
69  }
70 
71  diag(ASDecl->getLocation(),
72  "redundant access specifier has the same accessibility as the "
73  "previous access specifier")
74  << FixItHint::CreateRemoval(ASDecl->getSourceRange());
75  diag(LastASDecl->getLocation(), "previously declared here",
76  DiagnosticIDs::Note);
77  } else {
78  LastASDecl = ASDecl;
79  }
80  }
81 }
82 
83 } // namespace readability
84 } // namespace tidy
85 } // namespace clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//