brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.7 KiB · fffce20 Raw
94 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "NonPrivateMemberVariablesInClassesCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::misc {16 17namespace {18 19AST_MATCHER(CXXRecordDecl, hasMethods) {20  return std::distance(Node.method_begin(), Node.method_end()) != 0;21}22 23AST_MATCHER(CXXRecordDecl, hasNonStaticNonImplicitMethod) {24  return hasMethod(unless(anyOf(isStaticStorageClass(), isImplicit())))25      .matches(Node, Finder, Builder);26}27 28AST_MATCHER(CXXRecordDecl, hasNonPublicMemberVariable) {29  return cxxRecordDecl(has(fieldDecl(unless(isPublic()))))30      .matches(Node, Finder, Builder);31}32 33AST_POLYMORPHIC_MATCHER_P(boolean, AST_POLYMORPHIC_SUPPORTED_TYPES(Stmt, Decl),34                          bool, Boolean) {35  return Boolean;36}37 38} // namespace39 40NonPrivateMemberVariablesInClassesCheck::41    NonPrivateMemberVariablesInClassesCheck(StringRef Name,42                                            ClangTidyContext *Context)43    : ClangTidyCheck(Name, Context),44      IgnoreClassesWithAllMemberVariablesBeingPublic(45          Options.get("IgnoreClassesWithAllMemberVariablesBeingPublic", false)),46      IgnorePublicMemberVariables(47          Options.get("IgnorePublicMemberVariables", false)) {}48 49void NonPrivateMemberVariablesInClassesCheck::storeOptions(50    ClangTidyOptions::OptionMap &Opts) {51  Options.store(Opts, "IgnoreClassesWithAllMemberVariablesBeingPublic",52                IgnoreClassesWithAllMemberVariablesBeingPublic);53  Options.store(Opts, "IgnorePublicMemberVariables",54                IgnorePublicMemberVariables);55}56 57void NonPrivateMemberVariablesInClassesCheck::registerMatchers(58    MatchFinder *Finder) {59  // We can ignore structs/classes with all member variables being public.60  auto ShouldIgnoreRecord =61      allOf(boolean(IgnoreClassesWithAllMemberVariablesBeingPublic),62            unless(hasNonPublicMemberVariable()));63 64  // There are three visibility types: public, protected, private.65  // If we are ok with public fields, then we only want to complain about66  // protected fields, else we want to complain about all non-private fields.67  // We can ignore public member variables in structs/classes, in unions.68  auto InterestingField = IgnorePublicMemberVariables69                              ? fieldDecl(isProtected())70                              : fieldDecl(unless(isPrivate()));71 72  // We only want the records that not only contain the mutable data (non-static73  // member variables), but also have some logic (non-static, non-implicit74  // member functions).  We may optionally ignore records where all the member75  // variables are public.76  Finder->addMatcher(cxxRecordDecl(anyOf(isStruct(), isClass()), hasMethods(),77                                   hasNonStaticNonImplicitMethod(),78                                   unless(ShouldIgnoreRecord),79                                   forEach(InterestingField.bind("field")))80                         .bind("record"),81                     this);82}83 84void NonPrivateMemberVariablesInClassesCheck::check(85    const MatchFinder::MatchResult &Result) {86  const auto *Field = Result.Nodes.getNodeAs<FieldDecl>("field");87  assert(Field && "We should have the field we are going to complain about");88 89  diag(Field->getLocation(), "member variable %0 has %1 visibility")90      << Field << Field->getAccess();91}92 93} // namespace clang::tidy::misc94