clang-tools  7.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 
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(
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
std::map< std::string, std::string > OptionMap
static unsigned getNameSpecifierNestingLevel(const QualType &QType)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//