clang-tools  14.0.0git
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 #include "llvm/ADT/StringRef.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  .bind("memberExpression"),
45  this);
46 }
47 
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 overloaded -> 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  // Do not warn for CUDA built-in variables.
75  if (StringRef(BaseTypeName).startswith("__cuda_builtin_"))
76  return;
77 
78  SourceLocation MemberExprStartLoc = MemberExpression->getBeginLoc();
79  auto Diag =
80  diag(MemberExprStartLoc, "static member accessed through instance");
81 
82  if (BaseExpr->HasSideEffects(*AstContext) ||
83  getNameSpecifierNestingLevel(BaseType) > NameSpecifierNestingThreshold)
84  return;
85 
86  Diag << FixItHint::CreateReplacement(
87  CharSourceRange::getCharRange(MemberExprStartLoc,
88  MemberExpression->getMemberLoc()),
89  BaseTypeName + "::");
90 }
91 
92 } // namespace readability
93 } // namespace tidy
94 } // namespace clang
clang::tidy::ClangTidyOptions::OptionMap
llvm::StringMap< ClangTidyValue > OptionMap
Definition: ClangTidyOptions.h:115
clang::ast_matchers
Definition: AbseilMatcher.h:14
clang::tidy::readability::getNameSpecifierNestingLevel
static unsigned getNameSpecifierNestingLevel(const QualType &QType)
Definition: StaticAccessedThroughInstanceCheck.cpp:20
StaticAccessedThroughInstanceCheck.h
clang::clangd::check
bool check(llvm::StringRef File, llvm::function_ref< bool(const Position &)> ShouldCheckLine, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion)
Definition: Check.cpp:259
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27