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 | 40b6512d9ef7c68cc0c6bb5521f29616f4f79264 (patch) | |
| tree | 5d3de437ae77c131800c7fe00bfa4b4e4765e67d /clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp | |
| parent | 741d21f958fc76222c7cc4c6183e293ff86d1e1b (diff) | |
| download | bcm5719-llvm-40b6512d9ef7c68cc0c6bb5521f29616f4f79264.tar.gz bcm5719-llvm-40b6512d9ef7c68cc0c6bb5521f29616f4f79264.zip | |
[clang-tidy] Add new readability non-idiomatic static access check
Patch by: Lilla Barancsuk
Differential Revision: https://reviews.llvm.org/D35937
llvm-svn: 310371
Diffstat (limited to 'clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp')
| -rw-r--r-- | clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp new file mode 100644 index 00000000000..b1365772b59 --- /dev/null +++ b/clang-tools-extra/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 |

