diff options
author | Gabor Horvath <xazax.hun@gmail.com> | 2017-08-08 15:33:48 +0000 |
---|---|---|
committer | Gabor Horvath <xazax.hun@gmail.com> | 2017-08-08 15:33:48 +0000 |
commit | 8ec8591e4b75899a1d1dd3dd95482d57cc199357 (patch) | |
tree | e608039d60d891145fb42435e6575fdaae3e1249 /clang-tidy/readability | |
parent | 227f1ffb94cc42302698e9b1199f378000d2287f (diff) |
[clang-tidy] Add new readability non-idiomatic static access check
Patch by: Lilla Barancsuk
Differential Revision: https://reviews.llvm.org/D35937
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@310371 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'clang-tidy/readability')
4 files changed, 137 insertions, 0 deletions
diff --git a/clang-tidy/readability/CMakeLists.txt b/clang-tidy/readability/CMakeLists.txt index 8e6c6581..a130c9b4 100644 --- a/clang-tidy/readability/CMakeLists.txt +++ b/clang-tidy/readability/CMakeLists.txt @@ -25,6 +25,7 @@ add_clang_library(clangTidyReadabilityModule RedundantSmartptrGetCheck.cpp RedundantStringInitCheck.cpp SimplifyBooleanExprCheck.cpp + StaticAccessedThroughInstanceCheck.cpp StaticDefinitionInAnonymousNamespaceCheck.cpp UniqueptrDeleteReleaseCheck.cpp diff --git a/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tidy/readability/ReadabilityTidyModule.cpp index 81a9d6f3..395730dd 100644 --- a/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -32,6 +32,7 @@ #include "RedundantStringCStrCheck.h" #include "RedundantStringInitCheck.h" #include "SimplifyBooleanExprCheck.h" +#include "StaticAccessedThroughInstanceCheck.h" #include "StaticDefinitionInAnonymousNamespaceCheck.h" #include "UniqueptrDeleteReleaseCheck.h" @@ -70,6 +71,8 @@ public: "readability-redundant-function-ptr-dereference"); CheckFactories.registerCheck<RedundantMemberInitCheck>( "readability-redundant-member-init"); + CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>( + "readability-static-accessed-through-instance"); CheckFactories.registerCheck<StaticDefinitionInAnonymousNamespaceCheck>( "readability-static-definition-in-anonymous-namespace"); CheckFactories.registerCheck<readability::NamedParameterCheck>( diff --git a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp new file mode 100644 index 00000000..b1365772 --- /dev/null +++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp @@ -0,0 +1,90 @@ +//===--- StaticAccessedThroughInstanceCheck.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 "StaticAccessedThroughInstanceCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +static unsigned getNameSpecifierNestingLevel(const QualType &QType) { + if (const ElaboratedType *ElType = QType->getAs<ElaboratedType>()) { + const NestedNameSpecifier *NestedSpecifiers = ElType->getQualifier(); + unsigned NameSpecifierNestingLevel = 1; + do { + NameSpecifierNestingLevel++; + NestedSpecifiers = NestedSpecifiers->getPrefix(); + } while (NestedSpecifiers); + + return NameSpecifierNestingLevel; + } + return 0; +} + +void StaticAccessedThroughInstanceCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "NameSpecifierNestingThreshold", + NameSpecifierNestingThreshold); +} + +void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()), + varDecl(hasStaticStorageDuration()))), + unless(isInTemplateInstantiation())) + .bind("memberExpression"), + this); +} + +void StaticAccessedThroughInstanceCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *MemberExpression = + Result.Nodes.getNodeAs<MemberExpr>("memberExpression"); + + if (MemberExpression->getLocStart().isMacroID()) + return; + + const Expr *BaseExpr = MemberExpression->getBase(); + + // Do not warn for overlaoded -> operators. + if (isa<CXXOperatorCallExpr>(BaseExpr)) + return; + + QualType BaseType = + BaseExpr->getType()->isPointerType() + ? BaseExpr->getType()->getPointeeType().getUnqualifiedType() + : BaseExpr->getType().getUnqualifiedType(); + + const ASTContext *AstContext = Result.Context; + PrintingPolicy PrintingPolicyWithSupressedTag(AstContext->getLangOpts()); + PrintingPolicyWithSupressedTag.SuppressTagKeyword = true; + std::string BaseTypeName = + BaseType.getAsString(PrintingPolicyWithSupressedTag); + + SourceLocation MemberExprStartLoc = MemberExpression->getLocStart(); + auto Diag = + diag(MemberExprStartLoc, "static member accessed through instance"); + + if (BaseExpr->HasSideEffects(*AstContext) || + getNameSpecifierNestingLevel(BaseType) > NameSpecifierNestingThreshold) + return; + + Diag << FixItHint::CreateReplacement( + CharSourceRange::getCharRange(MemberExprStartLoc, + MemberExpression->getMemberLoc()), + BaseTypeName + "::"); +} + +} // namespace readability +} // namespace tidy +} // namespace clang diff --git a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h new file mode 100644 index 00000000..c2eebabe --- /dev/null +++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h @@ -0,0 +1,43 @@ +//===--- StaticAccessedThroughInstanceCheck.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_STATIC_ACCESSED_THROUGH_INSTANCE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// \@brief Checks for member expressions that access static members through +/// instances and replaces them with uses of the appropriate qualified-id. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-static-accessed-through-instance.html +class StaticAccessedThroughInstanceCheck : public ClangTidyCheck { +public: + StaticAccessedThroughInstanceCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + NameSpecifierNestingThreshold( + Options.get("NameSpecifierNestingThreshold", 3)) {} + + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + const unsigned NameSpecifierNestingThreshold; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H |