clang-tools 6.0.0

StaticAccessedThroughInstanceCheck.cpp
Go to the documentation of this file.
1 //===--- StaticAccessedThroughInstanceCheck.cpp - clang-tidy---------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "StaticAccessedThroughInstanceCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13
14 using namespace clang::ast_matchers;
15
16 namespace clang {
17 namespace tidy {
18 namespace readability {
19
20 static unsigned getNameSpecifierNestingLevel(const QualType &QType) {
21 if (const ElaboratedType *ElType = QType->getAs<ElaboratedType>()) {
22 const NestedNameSpecifier *NestedSpecifiers = ElType->getQualifier();
23 unsigned NameSpecifierNestingLevel = 1;
24 do {
25 NameSpecifierNestingLevel++;
26 NestedSpecifiers = NestedSpecifiers->getPrefix();
27 } while (NestedSpecifiers);
28
29 return NameSpecifierNestingLevel;
30 }
31 return 0;
32 }
33
34 void StaticAccessedThroughInstanceCheck::storeOptions(
35 ClangTidyOptions::OptionMap &Opts) {
36 Options.store(Opts, "NameSpecifierNestingThreshold",
37 NameSpecifierNestingThreshold);
38 }
39
40 void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) {
41 Finder->addMatcher(
42 memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()),
43 varDecl(hasStaticStorageDuration()))),
44 unless(isInTemplateInstantiation()))
45 .bind("memberExpression"),
46 this);
47 }
48
49 void StaticAccessedThroughInstanceCheck::check(
50 const MatchFinder::MatchResult &Result) {
51 const auto *MemberExpression =
52 Result.Nodes.getNodeAs<MemberExpr>("memberExpression");
53
54 if (MemberExpression->getLocStart().isMacroID())
55 return;
56
57 const Expr *BaseExpr = MemberExpression->getBase();
58
59 // Do not warn for overlaoded -> operators.
60 if (isa<CXXOperatorCallExpr>(BaseExpr))
61 return;
62
63 QualType BaseType =
64 BaseExpr->getType()->isPointerType()
65 ? BaseExpr->getType()->getPointeeType().getUnqualifiedType()
66 : BaseExpr->getType().getUnqualifiedType();
67
68 const ASTContext *AstContext = Result.Context;
69 PrintingPolicy PrintingPolicyWithSupressedTag(AstContext->getLangOpts());
70 PrintingPolicyWithSupressedTag.SuppressTagKeyword = true;
71 std::string BaseTypeName =
72 BaseType.getAsString(PrintingPolicyWithSupressedTag);
73
74 SourceLocation MemberExprStartLoc = MemberExpression->getLocStart();
75 auto Diag =
76 diag(MemberExprStartLoc, "static member accessed through instance");
77
78 if (BaseExpr->HasSideEffects(*AstContext) ||
79 getNameSpecifierNestingLevel(BaseType) > NameSpecifierNestingThreshold)
80 return;
81
82 Diag << FixItHint::CreateReplacement(
83 CharSourceRange::getCharRange(MemberExprStartLoc,
84 MemberExpression->getMemberLoc()),
85 BaseTypeName + "::");
86 }
87
88 } // namespace readability
89 } // namespace tidy
90 } // namespace clang
clang::ast_matchers
Definition: ClangTidyDiagnosticConsumer.h:27
clang::tidy::ClangTidyOptions::OptionMap
std::map< std::string, std::string > OptionMap
Definition: ClangTidyOptions.h:99
clang::tidy::readability::getNameSpecifierNestingLevel
static unsigned getNameSpecifierNestingLevel(const QualType &QType)
Definition: StaticAccessedThroughInstanceCheck.cpp:20
clang
Definition: AndroidTidyModule.cpp:28
StaticAccessedThroughInstanceCheck.h