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