clang-tools 10.0.0

StaticAccessedThroughInstanceCheck.cpp
Go to the documentation of this file.
1 //===--- StaticAccessedThroughInstanceCheck.cpp - clang-tidy---------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "StaticAccessedThroughInstanceCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12
13 using namespace clang::ast_matchers;
14
15 namespace clang {
16 namespace tidy {
17 namespace readability {
18
19 static unsigned getNameSpecifierNestingLevel(const QualType &QType) {
20 if (const ElaboratedType *ElType = QType->getAs<ElaboratedType>()) {
21 const NestedNameSpecifier *NestedSpecifiers = ElType->getQualifier();
22 unsigned NameSpecifierNestingLevel = 1;
23 do {
24 NameSpecifierNestingLevel++;
25 NestedSpecifiers = NestedSpecifiers->getPrefix();
26 } while (NestedSpecifiers);
27
28 return NameSpecifierNestingLevel;
29 }
30 return 0;
31 }
32
33 void StaticAccessedThroughInstanceCheck::storeOptions(
34 ClangTidyOptions::OptionMap &Opts) {
35 Options.store(Opts, "NameSpecifierNestingThreshold",
36 NameSpecifierNestingThreshold);
37 }
38
39 void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) {
40 Finder->addMatcher(
41 memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()),
42 varDecl(hasStaticStorageDuration()))),
43 unless(isInTemplateInstantiation()))
44 .bind("memberExpression"),
45 this);
46 }
47
48 void StaticAccessedThroughInstanceCheck::check(
49 const MatchFinder::MatchResult &Result) {
50 const auto *MemberExpression =
51 Result.Nodes.getNodeAs<MemberExpr>("memberExpression");
52
53 if (MemberExpression->getBeginLoc().isMacroID())
54 return;
55
56 const Expr *BaseExpr = MemberExpression->getBase();
57
58 // Do not warn for overlaoded -> operators.
59 if (isa<CXXOperatorCallExpr>(BaseExpr))
60 return;
61
62 QualType BaseType =
63 BaseExpr->getType()->isPointerType()
64 ? BaseExpr->getType()->getPointeeType().getUnqualifiedType()
65 : BaseExpr->getType().getUnqualifiedType();
66
67 const ASTContext *AstContext = Result.Context;
68 PrintingPolicy PrintingPolicyWithSupressedTag(AstContext->getLangOpts());
69 PrintingPolicyWithSupressedTag.SuppressTagKeyword = true;
70 PrintingPolicyWithSupressedTag.SuppressUnwrittenScope = true;
71 std::string BaseTypeName =
72 BaseType.getAsString(PrintingPolicyWithSupressedTag);
73
74 SourceLocation MemberExprStartLoc = MemberExpression->getBeginLoc();
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: AbseilMatcher.h:14
clang::tidy::ClangTidyOptions::OptionMap
std::map< std::string, std::string > OptionMap
Definition: ClangTidyOptions.h:97
clang::tidy::readability::getNameSpecifierNestingLevel
static unsigned getNameSpecifierNestingLevel(const QualType &QType)
Definition: StaticAccessedThroughInstanceCheck.cpp:19
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
StaticAccessedThroughInstanceCheck.h