Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[clang-tidy] Non-private member variables in classes (MISRA, CppCoreG…
…uidelines, HICPP) Summary: Finds classes that not only contain the data (non-static member variables), but also have logic (non-static member functions), and diagnoses all member variables that have any other scope other than `private`. They should be made `private`, and manipulated exclusively via the member functions. Optionally, classes with all member variables being `public` could be ignored, and optionally all `public` member variables could be ignored. Options ------- * IgnoreClassesWithAllMemberVariablesBeingPublic Allows to completely ignore classes if **all** the member variables in that class have `public` visibility. * IgnorePublicMemberVariables Allows to ignore (not diagnose) **all** the member variables with `public` visibility scope. References: * MISRA 11-0-1 Member data in non-POD class types shall be private. * https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c2-use-class-if-the-class-has-an-invariant-use-struct-if-the-data-members-can-vary-independently * https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-private * https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rh-protected Reviewers: JonasToth, aaron.ballman, alexfh, hokein, xazax.hun Reviewed By: aaron.ballman Subscribers: Eugene.Zelenko, zinovy.nis, cfe-commits, rnkovacs, nemanjai, mgorny, xazax.hun, kbarton Tags: #clang-tools-extra Differential Revision: https://reviews.llvm.org/D52771 llvm-svn: 344757
- Loading branch information
Showing
10 changed files
with
588 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
clang-tools-extra/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
//===--- NonPrivateMemberVariablesInClassesCheck.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 "NonPrivateMemberVariablesInClassesCheck.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/ASTMatchers/ASTMatchFinder.h" | ||
|
||
using namespace clang::ast_matchers; | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace misc { | ||
|
||
namespace { | ||
|
||
AST_MATCHER(CXXRecordDecl, hasMethods) { | ||
return std::distance(Node.method_begin(), Node.method_end()) != 0; | ||
} | ||
|
||
AST_MATCHER(CXXRecordDecl, hasNonStaticMethod) { | ||
return hasMethod(unless(isStaticStorageClass())) | ||
.matches(Node, Finder, Builder); | ||
} | ||
|
||
AST_MATCHER(CXXRecordDecl, hasNonPublicMemberVariable) { | ||
return cxxRecordDecl(has(fieldDecl(unless(isPublic())))) | ||
.matches(Node, Finder, Builder); | ||
} | ||
|
||
AST_POLYMORPHIC_MATCHER_P(boolean, AST_POLYMORPHIC_SUPPORTED_TYPES(Stmt, Decl), | ||
bool, Boolean) { | ||
return Boolean; | ||
} | ||
|
||
} // namespace | ||
|
||
NonPrivateMemberVariablesInClassesCheck:: | ||
NonPrivateMemberVariablesInClassesCheck(StringRef Name, | ||
ClangTidyContext *Context) | ||
: ClangTidyCheck(Name, Context), | ||
IgnoreClassesWithAllMemberVariablesBeingPublic( | ||
Options.get("IgnoreClassesWithAllMemberVariablesBeingPublic", false)), | ||
IgnorePublicMemberVariables( | ||
Options.get("IgnorePublicMemberVariables", false)) {} | ||
|
||
void NonPrivateMemberVariablesInClassesCheck::registerMatchers( | ||
MatchFinder *Finder) { | ||
if (!getLangOpts().CPlusPlus) | ||
return; | ||
|
||
// We can ignore structs/classes with all member variables being public. | ||
auto ShouldIgnoreRecord = | ||
allOf(boolean(IgnoreClassesWithAllMemberVariablesBeingPublic), | ||
unless(hasNonPublicMemberVariable())); | ||
|
||
// We only want the records that not only contain the mutable data (non-static | ||
// member variables), but also have some logic (non-static member functions). | ||
// We may optionally ignore records where all the member variables are public. | ||
auto RecordIsInteresting = | ||
allOf(anyOf(isStruct(), isClass()), hasMethods(), hasNonStaticMethod(), | ||
unless(ShouldIgnoreRecord)); | ||
|
||
// There are three visibility types: public, protected, private. | ||
// If we are ok with public fields, then we only want to complain about | ||
// protected fields, else we want to complain about all non-private fields. | ||
// We can ignore public member variables in structs/classes, in unions. | ||
auto InterestingField = fieldDecl( | ||
IgnorePublicMemberVariables ? isProtected() : unless(isPrivate())); | ||
|
||
Finder->addMatcher(cxxRecordDecl(RecordIsInteresting, | ||
forEach(InterestingField.bind("field"))) | ||
.bind("record"), | ||
this); | ||
} | ||
|
||
void NonPrivateMemberVariablesInClassesCheck::check( | ||
const MatchFinder::MatchResult &Result) { | ||
const auto *Field = Result.Nodes.getNodeAs<FieldDecl>("field"); | ||
assert(Field && "We should have the field we are going to complain about"); | ||
|
||
diag(Field->getLocation(), "member variable %0 has %1 visibility") | ||
<< Field << Field->getAccess(); | ||
} | ||
|
||
} // namespace misc | ||
} // namespace tidy | ||
} // namespace clang |
46 changes: 46 additions & 0 deletions
46
clang-tools-extra/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
//===--- NonPrivateMemberVariablesInClassesCheck.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_MISC_NONPRIVATEMEMBERVARIABLESINCLASSESCHECK_H | ||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NONPRIVATEMEMBERVARIABLESINCLASSESCHECK_H | ||
|
||
#include "../ClangTidy.h" | ||
|
||
namespace clang { | ||
namespace tidy { | ||
namespace misc { | ||
|
||
/// This checker finds classes that not only contain the data | ||
/// (non-static member variables), but also have logic (non-static member | ||
/// functions), and diagnoses all member variables that have any other scope | ||
/// other than `private`. They should be made `private`, and manipulated | ||
/// exclusively via the member functions. | ||
/// | ||
/// Optionally, classes with all member variables being `public` could be | ||
/// ignored and optionally all `public` member variables could be ignored. | ||
/// | ||
/// For the user-facing documentation see: | ||
/// http://clang.llvm.org/extra/clang-tidy/checks/misc-non-private-member-variables-in-classes.html | ||
class NonPrivateMemberVariablesInClassesCheck : public ClangTidyCheck { | ||
public: | ||
NonPrivateMemberVariablesInClassesCheck(StringRef Name, | ||
ClangTidyContext *Context); | ||
void registerMatchers(ast_matchers::MatchFinder *Finder) override; | ||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override; | ||
|
||
private: | ||
const bool IgnoreClassesWithAllMemberVariablesBeingPublic; | ||
const bool IgnorePublicMemberVariables; | ||
}; | ||
|
||
} // namespace misc | ||
} // namespace tidy | ||
} // namespace clang | ||
|
||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NONPRIVATEMEMBERVARIABLESINCLASSESCHECK_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
...clang-tidy/checks/cppcoreguidelines-non-private-member-variables-in-classes.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.. title:: clang-tidy - cppcoreguidelines-non-private-member-variables-in-classes | ||
.. meta:: | ||
:http-equiv=refresh: 5;URL=misc-non-private-member-variables-in-classes.html | ||
|
||
cppcoreguidelines-non-private-member-variables-in-classes | ||
========================================================= | ||
|
||
The cppcoreguidelines-non-private-member-variables-in-classes check is an alias, | ||
please see | ||
`misc-non-private-member-variables-in-classes <misc-non-private-member-variables-in-classes.html>`_ | ||
for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
...s-extra/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
.. title:: clang-tidy - misc-non-private-member-variables-in-classes | ||
|
||
misc-non-private-member-variables-in-classes | ||
============================================ | ||
|
||
`cppcoreguidelines-non-private-member-variables-in-classes` redirects here | ||
as an alias for this check. | ||
|
||
Finds classes that contain non-static data members in addition to non-static | ||
member functions and diagnose all data members declared with a non-``public`` | ||
access specifier. The data members should be declared as ``private`` and | ||
accessed through member functions instead of exposed to derived classes or | ||
class consumers. | ||
|
||
Options | ||
------- | ||
|
||
.. option:: IgnoreClassesWithAllMemberVariablesBeingPublic | ||
|
||
Allows to completely ignore classes if **all** the member variables in that | ||
class a declared with a ``public`` access specifier. | ||
|
||
.. option:: IgnorePublicMemberVariables | ||
|
||
Allows to ignore (not diagnose) **all** the member variables declared with | ||
a ``public`` access specifier. |
Oops, something went wrong.