clang-tools  14.0.0git
LambdaFunctionNameCheck.cpp
Go to the documentation of this file.
1 //===--- LambdaFunctionNameCheck.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 "clang/Frontend/CompilerInstance.h"
13 #include "clang/Lex/MacroInfo.h"
14 #include "clang/Lex/Preprocessor.h"
15 
16 using namespace clang::ast_matchers;
17 
18 namespace clang {
19 namespace tidy {
20 namespace bugprone {
21 
22 namespace {
23 
24 // Keep track of macro expansions that contain both __FILE__ and __LINE__. If
25 // such a macro also uses __func__ or __FUNCTION__, we don't want to issue a
26 // warning because __FILE__ and __LINE__ may be useful even if __func__ or
27 // __FUNCTION__ is not, especially if the macro could be used in the context of
28 // either a function body or a lambda body.
29 class MacroExpansionsWithFileAndLine : public PPCallbacks {
30 public:
31  explicit MacroExpansionsWithFileAndLine(
32  LambdaFunctionNameCheck::SourceRangeSet *SME)
33  : SuppressMacroExpansions(SME) {}
34 
35  void MacroExpands(const Token &MacroNameTok,
36  const MacroDefinition &MD, SourceRange Range,
37  const MacroArgs *Args) override {
38  bool HasFile = false;
39  bool HasLine = false;
40  for (const auto& T : MD.getMacroInfo()->tokens()) {
41  if (T.is(tok::identifier)) {
42  StringRef IdentName = T.getIdentifierInfo()->getName();
43  if (IdentName == "__FILE__") {
44  HasFile = true;
45  } else if (IdentName == "__LINE__") {
46  HasLine = true;
47  }
48  }
49  }
50  if (HasFile && HasLine) {
51  SuppressMacroExpansions->insert(Range);
52  }
53  }
54 
55 private:
56  LambdaFunctionNameCheck::SourceRangeSet* SuppressMacroExpansions;
57 };
58 
59 } // namespace
60 
61 void LambdaFunctionNameCheck::registerMatchers(MatchFinder *Finder) {
62  // Match on PredefinedExprs inside a lambda.
63  Finder->addMatcher(predefinedExpr(hasAncestor(lambdaExpr())).bind("E"),
64  this);
65 }
66 
67 void LambdaFunctionNameCheck::registerPPCallbacks(
68  const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
69  PP->addPPCallbacks(std::make_unique<MacroExpansionsWithFileAndLine>(
70  &SuppressMacroExpansions));
71 }
72 
73 void LambdaFunctionNameCheck::check(const MatchFinder::MatchResult &Result) {
74  const auto *E = Result.Nodes.getNodeAs<PredefinedExpr>("E");
75  if (E->getIdentKind() != PredefinedExpr::Func &&
76  E->getIdentKind() != PredefinedExpr::Function) {
77  // We don't care about other PredefinedExprs.
78  return;
79  }
80  if (E->getLocation().isMacroID()) {
81  auto ER =
82  Result.SourceManager->getImmediateExpansionRange(E->getLocation());
83  if (SuppressMacroExpansions.find(ER.getAsRange()) !=
84  SuppressMacroExpansions.end()) {
85  // This is a macro expansion for which we should not warn.
86  return;
87  }
88  }
89  diag(E->getLocation(),
90  "inside a lambda, '%0' expands to the name of the function call "
91  "operator; consider capturing the name of the enclosing function "
92  "explicitly")
93  << PredefinedExpr::getIdentKindName(E->getIdentKind());
94 }
95 
96 } // namespace bugprone
97 } // namespace tidy
98 } // namespace clang
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
clang::doc::MD
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
clang::ast_matchers
Definition: AbseilMatcher.h:14
Args
llvm::json::Object Args
Definition: Trace.cpp:139
LambdaFunctionNameCheck.h
clang::tidy::bugprone::PP
static Preprocessor * PP
Definition: BadSignalToKillThreadCheck.cpp:29
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
SM
const SourceManager & SM
Definition: IncludeCleaner.cpp:140