129dc0b17SAaron Ballman //===--- RedundantAccessSpecifiersCheck.cpp - clang-tidy ------------------===// 229dc0b17SAaron Ballman // 329dc0b17SAaron Ballman // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 429dc0b17SAaron Ballman // See https://llvm.org/LICENSE.txt for license information. 529dc0b17SAaron Ballman // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 629dc0b17SAaron Ballman // 729dc0b17SAaron Ballman //===----------------------------------------------------------------------===// 829dc0b17SAaron Ballman 929dc0b17SAaron Ballman #include "RedundantAccessSpecifiersCheck.h" 1029dc0b17SAaron Ballman #include "clang/AST/ASTContext.h" 1129dc0b17SAaron Ballman #include "clang/ASTMatchers/ASTMatchFinder.h" 1229dc0b17SAaron Ballman 1329dc0b17SAaron Ballman using namespace clang::ast_matchers; 1429dc0b17SAaron Ballman 15*7d2ea6c4SCarlos Galvez namespace clang::tidy::readability { 1629dc0b17SAaron Ballman registerMatchers(MatchFinder * Finder)1729dc0b17SAaron Ballmanvoid RedundantAccessSpecifiersCheck::registerMatchers(MatchFinder *Finder) { 1829dc0b17SAaron Ballman Finder->addMatcher( 1929dc0b17SAaron Ballman cxxRecordDecl(has(accessSpecDecl())).bind("redundant-access-specifiers"), 2029dc0b17SAaron Ballman this); 2129dc0b17SAaron Ballman } 2229dc0b17SAaron Ballman check(const MatchFinder::MatchResult & Result)2329dc0b17SAaron Ballmanvoid RedundantAccessSpecifiersCheck::check( 2429dc0b17SAaron Ballman const MatchFinder::MatchResult &Result) { 2529dc0b17SAaron Ballman const auto *MatchedDecl = 2629dc0b17SAaron Ballman Result.Nodes.getNodeAs<CXXRecordDecl>("redundant-access-specifiers"); 2729dc0b17SAaron Ballman 2829dc0b17SAaron Ballman const AccessSpecDecl *LastASDecl = nullptr; 2929dc0b17SAaron Ballman for (DeclContext::specific_decl_iterator<AccessSpecDecl> 3029dc0b17SAaron Ballman AS(MatchedDecl->decls_begin()), 3129dc0b17SAaron Ballman ASEnd(MatchedDecl->decls_end()); 3229dc0b17SAaron Ballman AS != ASEnd; ++AS) { 3329dc0b17SAaron Ballman const AccessSpecDecl *ASDecl = *AS; 3429dc0b17SAaron Ballman 3529dc0b17SAaron Ballman // Ignore macro expansions. 3629dc0b17SAaron Ballman if (ASDecl->getLocation().isMacroID()) { 3729dc0b17SAaron Ballman LastASDecl = ASDecl; 3829dc0b17SAaron Ballman continue; 3929dc0b17SAaron Ballman } 4029dc0b17SAaron Ballman 4129dc0b17SAaron Ballman if (LastASDecl == nullptr) { 4229dc0b17SAaron Ballman // First declaration. 4329dc0b17SAaron Ballman LastASDecl = ASDecl; 4429dc0b17SAaron Ballman 4529dc0b17SAaron Ballman if (CheckFirstDeclaration) { 4629dc0b17SAaron Ballman AccessSpecifier DefaultSpecifier = 4729dc0b17SAaron Ballman MatchedDecl->isClass() ? AS_private : AS_public; 4829dc0b17SAaron Ballman if (ASDecl->getAccess() == DefaultSpecifier) { 4929dc0b17SAaron Ballman diag(ASDecl->getLocation(), 5029dc0b17SAaron Ballman "redundant access specifier has the same accessibility as the " 5129dc0b17SAaron Ballman "implicit access specifier") 5229dc0b17SAaron Ballman << FixItHint::CreateRemoval(ASDecl->getSourceRange()); 5329dc0b17SAaron Ballman } 5429dc0b17SAaron Ballman } 5529dc0b17SAaron Ballman 5629dc0b17SAaron Ballman continue; 5729dc0b17SAaron Ballman } 5829dc0b17SAaron Ballman 5929dc0b17SAaron Ballman if (LastASDecl->getAccess() == ASDecl->getAccess()) { 6029dc0b17SAaron Ballman // Ignore macro expansions. 6129dc0b17SAaron Ballman if (LastASDecl->getLocation().isMacroID()) { 6229dc0b17SAaron Ballman LastASDecl = ASDecl; 6329dc0b17SAaron Ballman continue; 6429dc0b17SAaron Ballman } 6529dc0b17SAaron Ballman 6629dc0b17SAaron Ballman diag(ASDecl->getLocation(), 6729dc0b17SAaron Ballman "redundant access specifier has the same accessibility as the " 6829dc0b17SAaron Ballman "previous access specifier") 6929dc0b17SAaron Ballman << FixItHint::CreateRemoval(ASDecl->getSourceRange()); 7029dc0b17SAaron Ballman diag(LastASDecl->getLocation(), "previously declared here", 7129dc0b17SAaron Ballman DiagnosticIDs::Note); 7229dc0b17SAaron Ballman } else { 7329dc0b17SAaron Ballman LastASDecl = ASDecl; 7429dc0b17SAaron Ballman } 7529dc0b17SAaron Ballman } 7629dc0b17SAaron Ballman } 7729dc0b17SAaron Ballman 78*7d2ea6c4SCarlos Galvez } // namespace clang::tidy::readability 79