Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -7,6 +7,7 @@ ContainerSizeEmptyCheck.cpp DeleteNullPointerCheck.cpp DeletedDefaultCheck.cpp + DuplicatedAccessSpecifiersCheck.cpp ElseAfterReturnCheck.cpp FunctionSizeCheck.cpp IdentifierNamingCheck.cpp Index: clang-tidy/readability/DuplicatedAccessSpecifiersCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/DuplicatedAccessSpecifiersCheck.h @@ -0,0 +1,35 @@ +//===--- DuplicatedAccessSpecifiersCheck.h - clang-tidy ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DUPLICATEDACCESSSPECIFIERSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DUPLICATEDACCESSSPECIFIERSCHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Detects duplicated access specifiers inside classes, structs, and unions. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-duplicated-access-specifiers.html +class DuplicatedAccessSpecifiersCheck : public ClangTidyCheck { +public: + DuplicatedAccessSpecifiersCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DUPLICATEDACCESSSPECIFIERSCHECK_H Index: clang-tidy/readability/DuplicatedAccessSpecifiersCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/DuplicatedAccessSpecifiersCheck.cpp @@ -0,0 +1,53 @@ +//===--- DuplicatedAccessSpecifiersCheck.cpp - clang-tidy -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DuplicatedAccessSpecifiersCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +void DuplicatedAccessSpecifiersCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + cxxRecordDecl(has(accessSpecDecl())) + .bind("duplicated-access-specifiers"), this); +} + +void DuplicatedAccessSpecifiersCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = + Result.Nodes.getNodeAs("duplicated-access-specifiers"); + + AccessSpecDecl const *lastAccessDecl = nullptr; + for (DeclContext::specific_decl_iterator + NS(MatchedDecl->decls_begin()), + NSEnd(MatchedDecl->decls_end()); + NS != NSEnd; ++NS) { + const auto *decl = *NS; + + if (lastAccessDecl != nullptr && + lastAccessDecl->getAccess() == decl->getAccess()) { + diag(decl->getLocation(), "duplicated access specifier") + << MatchedDecl + << FixItHint::CreateRemoval(decl->getSourceRange()); + diag(lastAccessDecl->getLocation(), "previously declared here", + DiagnosticIDs::Note); + } else { + lastAccessDecl = decl; + } + } +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -16,6 +16,7 @@ #include "ContainerSizeEmptyCheck.h" #include "DeleteNullPointerCheck.h" #include "DeletedDefaultCheck.h" +#include "DuplicatedAccessSpecifiersCheck.h" #include "ElseAfterReturnCheck.h" #include "FunctionSizeCheck.h" #include "IdentifierNamingCheck.h" @@ -61,6 +62,8 @@ "readability-delete-null-pointer"); CheckFactories.registerCheck( "readability-deleted-default"); + CheckFactories.registerCheck( + "readability-duplicated-access-specifiers"); CheckFactories.registerCheck( "readability-else-after-return"); CheckFactories.registerCheck( Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -192,6 +192,12 @@ Checks for functions with a ``const``-qualified return type and recommends removal of the ``const`` keyword. +- New :doc:`readability-duplicated-access-specifiers + ` check. + + Finds classes, structs, and unions that contain duplicated member + access specifiers. + - New :doc:`readability-magic-numbers ` check. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -238,6 +238,7 @@ readability-container-size-empty readability-delete-null-pointer readability-deleted-default + readability-duplicated-access-specifiers readability-else-after-return readability-function-size readability-identifier-naming Index: docs/clang-tidy/checks/readability-duplicated-access-specifiers.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/readability-duplicated-access-specifiers.rst @@ -0,0 +1,26 @@ +.. title:: clang-tidy - readability-duplicated-access-specifiers + +readability-duplicated-access-specifiers +======================================== + +Finds classes, structs and unions containing duplicated member access specifiers +that can be removed. + +Examples: + +.. code-block:: c++ + + class Foo { + public: + int x; + int y; + public: + int z; + protected: + int a; + public: + int c; + } + +In the example above, the second ``public`` declaration can be removed without +any changes of behavior. Index: test/clang-tidy/readability-duplicated-access-specifiers.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-duplicated-access-specifiers.cpp @@ -0,0 +1,74 @@ +// RUN: %check_clang_tidy %s readability-duplicated-access-specifiers %t + +class FooPublic { +public: + int a; +public: // comment-0 + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: duplicated access specifier [readability-duplicated-access-specifiers] + // CHECK-MESSAGES: :[[@LINE-4]]:1: note: previously declared here + // CHECK-FIXES: {{^}}// comment-0{{$}} + int b; +private: + int c; +}; + +struct StructPublic { +public: + int a; +public: // comment-1 + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: duplicated access specifier [readability-duplicated-access-specifiers] + // CHECK-MESSAGES: :[[@LINE-4]]:1: note: previously declared here + // CHECK-FIXES: {{^}}// comment-1{{$}} + int b; +private: + int c; +}; + +union UnionPublic { +public: + int a; +public: // comment-2 + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: duplicated access specifier [readability-duplicated-access-specifiers] + // CHECK-MESSAGES: :[[@LINE-4]]:1: note: previously declared here + // CHECK-FIXES: {{^}}// comment-2{{$}} + int b; +private: + int c; +}; + +class FooProtected { +protected: + int a; +protected: // comment-3 + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: duplicated access specifier [readability-duplicated-access-specifiers] + // CHECK-MESSAGES: :[[@LINE-4]]:1: note: previously declared here + // CHECK-FIXES: {{^}}// comment-3{{$}} + int b; +private: + int c; +}; + +class FooPrivate { +private: + int a; +private: // comment-4 + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: duplicated access specifier [readability-duplicated-access-specifiers] + // CHECK-MESSAGES: :[[@LINE-4]]:1: note: previously declared here + // CHECK-FIXES: {{^}}// comment-4{{$}} + int b; +public: + int c; +}; + +class Valid { +private: + int a; +public: + int b; +private: + int c; +protected: + int d; +public: + int e; +};