clang-tools  12.0.0git
RenamerClangTidyCheck.cpp
Go to the documentation of this file.
1 //===--- RenamerClangTidyCheck.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 "ASTUtils.h"
11 #include "clang/AST/CXXInheritance.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Frontend/CompilerInstance.h"
14 #include "clang/Lex/PPCallbacks.h"
15 #include "clang/Lex/Preprocessor.h"
16 #include "llvm/ADT/DenseMapInfo.h"
17 #include "llvm/ADT/PointerIntPair.h"
18 
19 #define DEBUG_TYPE "clang-tidy"
20 
21 using namespace clang::ast_matchers;
22 
23 namespace llvm {
24 
25 /// Specialisation of DenseMapInfo to allow NamingCheckId objects in DenseMaps
26 template <>
29 
30  static inline NamingCheckId getEmptyKey() {
31  return NamingCheckId(
32  clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-1)),
33  "EMPTY");
34  }
35 
36  static inline NamingCheckId getTombstoneKey() {
37  return NamingCheckId(
38  clang::SourceLocation::getFromRawEncoding(static_cast<unsigned>(-2)),
39  "TOMBSTONE");
40  }
41 
42  static unsigned getHashValue(NamingCheckId Val) {
43  assert(Val != getEmptyKey() && "Cannot hash the empty key!");
44  assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!");
45 
46  std::hash<NamingCheckId::second_type> SecondHash;
47  return Val.first.getRawEncoding() + SecondHash(Val.second);
48  }
49 
50  static bool isEqual(const NamingCheckId &LHS, const NamingCheckId &RHS) {
51  if (RHS == getEmptyKey())
52  return LHS == getEmptyKey();
53  if (RHS == getTombstoneKey())
54  return LHS == getTombstoneKey();
55  return LHS == RHS;
56  }
57 };
58 
59 } // namespace llvm
60 
61 namespace clang {
62 namespace tidy {
63 
64 namespace {
65 
66 /// Callback supplies macros to RenamerClangTidyCheck::checkMacro
67 class RenamerClangTidyCheckPPCallbacks : public PPCallbacks {
68 public:
69  RenamerClangTidyCheckPPCallbacks(Preprocessor *PP,
70  RenamerClangTidyCheck *Check)
71  : PP(PP), Check(Check) {}
72 
73  /// MacroDefined calls checkMacro for macros in the main file
74  void MacroDefined(const Token &MacroNameTok,
75  const MacroDirective *MD) override {
76  if (MD->getMacroInfo()->isBuiltinMacro())
77  return;
78  if (PP->getSourceManager().isWrittenInBuiltinFile(
79  MacroNameTok.getLocation()))
80  return;
81  if (PP->getSourceManager().isWrittenInCommandLineFile(
82  MacroNameTok.getLocation()))
83  return;
84  Check->checkMacro(PP->getSourceManager(), MacroNameTok, MD->getMacroInfo());
85  }
86 
87  /// MacroExpands calls expandMacro for macros in the main file
88  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
89  SourceRange /*Range*/,
90  const MacroArgs * /*Args*/) override {
91  Check->expandMacro(MacroNameTok, MD.getMacroInfo());
92  }
93 
94 private:
95  Preprocessor *PP;
96  RenamerClangTidyCheck *Check;
97 };
98 
99 } // namespace
100 
101 RenamerClangTidyCheck::RenamerClangTidyCheck(StringRef CheckName,
102  ClangTidyContext *Context)
103  : ClangTidyCheck(CheckName, Context),
104  AggressiveDependentMemberLookup(
105  Options.getLocalOrGlobal("AggressiveDependentMemberLookup", false)) {}
107 
109  Options.store(Opts, "AggressiveDependentMemberLookup",
110  AggressiveDependentMemberLookup);
111 }
112 
113 void RenamerClangTidyCheck::registerMatchers(MatchFinder *Finder) {
114  Finder->addMatcher(namedDecl().bind("decl"), this);
115  Finder->addMatcher(usingDecl().bind("using"), this);
116  Finder->addMatcher(declRefExpr().bind("declRef"), this);
117  Finder->addMatcher(cxxConstructorDecl(unless(isImplicit())).bind("classRef"),
118  this);
119  Finder->addMatcher(cxxDestructorDecl(unless(isImplicit())).bind("classRef"),
120  this);
121  Finder->addMatcher(typeLoc().bind("typeLoc"), this);
122  Finder->addMatcher(nestedNameSpecifierLoc().bind("nestedNameLoc"), this);
123  auto MemberRestrictions =
124  unless(forFunction(anyOf(isDefaulted(), isImplicit())));
125  Finder->addMatcher(memberExpr(MemberRestrictions).bind("memberExpr"), this);
126  Finder->addMatcher(
127  cxxDependentScopeMemberExpr(MemberRestrictions).bind("depMemberExpr"),
128  this);
129 }
130 
132  const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
133  ModuleExpanderPP->addPPCallbacks(
134  std::make_unique<RenamerClangTidyCheckPPCallbacks>(ModuleExpanderPP,
135  this));
136 }
137 
139  const RenamerClangTidyCheck::NamingCheckId &Decl, SourceRange Range,
140  SourceManager *SourceMgr) {
141  // Do nothing if the provided range is invalid.
142  if (Range.isInvalid())
143  return;
144 
145  // If we have a source manager, use it to convert to the spelling location for
146  // performing the fix. This is necessary because macros can map the same
147  // spelling location to different source locations, and we only want to fix
148  // the token once, before it is expanded by the macro.
149  SourceLocation FixLocation = Range.getBegin();
150  if (SourceMgr)
151  FixLocation = SourceMgr->getSpellingLoc(FixLocation);
152  if (FixLocation.isInvalid())
153  return;
154 
155  // Try to insert the identifier location in the Usages map, and bail out if it
156  // is already in there
158  NamingCheckFailures[Decl];
159 
160  if (!Failure.ShouldFix())
161  return;
162 
163  if (SourceMgr && SourceMgr->isWrittenInScratchSpace(FixLocation))
165 
166  if (!utils::rangeCanBeFixed(Range, SourceMgr))
168 
169  Failure.RawUsageLocs.insert(FixLocation.getRawEncoding());
170 }
171 
172 void RenamerClangTidyCheck::addUsage(const NamedDecl *Decl, SourceRange Range,
173  SourceManager *SourceMgr) {
174  Decl = cast<NamedDecl>(Decl->getCanonicalDecl());
175  return addUsage(RenamerClangTidyCheck::NamingCheckId(Decl->getLocation(),
176  Decl->getNameAsString()),
177  Range, SourceMgr);
178 }
179 
180 const NamedDecl *findDecl(const RecordDecl &RecDecl, StringRef DeclName) {
181  for (const Decl *D : RecDecl.decls()) {
182  if (const auto *ND = dyn_cast<NamedDecl>(D)) {
183  if (ND->getDeclName().isIdentifier() && ND->getName().equals(DeclName))
184  return ND;
185  }
186  }
187  return nullptr;
188 }
189 
190 namespace {
191 class NameLookup {
192  llvm::PointerIntPair<const NamedDecl *, 1, bool> Data;
193 
194 public:
195  explicit NameLookup(const NamedDecl *ND) : Data(ND, false) {}
196  explicit NameLookup(llvm::NoneType) : Data(nullptr, true) {}
197  explicit NameLookup(std::nullptr_t) : Data(nullptr, false) {}
198  NameLookup() : NameLookup(nullptr) {}
199 
200  bool hasMultipleResolutions() const { return Data.getInt(); }
201  const NamedDecl *getDecl() const {
202  assert(!hasMultipleResolutions() && "Found multiple decls");
203  return Data.getPointer();
204  }
205  operator bool() const { return !hasMultipleResolutions(); }
206  const NamedDecl *operator*() const { return getDecl(); }
207 };
208 } // namespace
209 
210 /// Returns a decl matching the \p DeclName in \p Parent or one of its base
211 /// classes. If \p AggressiveTemplateLookup is `true` then it will check
212 /// template dependent base classes as well.
213 /// If a matching decl is found in multiple base classes then it will return a
214 /// flag indicating the multiple resolutions.
215 NameLookup findDeclInBases(const CXXRecordDecl &Parent, StringRef DeclName,
216  bool AggressiveTemplateLookup) {
217  if (!Parent.hasDefinition())
218  return NameLookup(nullptr);
219  if (const NamedDecl *InClassRef = findDecl(Parent, DeclName))
220  return NameLookup(InClassRef);
221  const NamedDecl *Found = nullptr;
222 
223  for (CXXBaseSpecifier Base : Parent.bases()) {
224  const auto *Record = Base.getType()->getAsCXXRecordDecl();
225  if (!Record && AggressiveTemplateLookup) {
226  if (const auto *TST =
227  Base.getType()->getAs<TemplateSpecializationType>()) {
228  if (const auto *TD = llvm::dyn_cast_or_null<ClassTemplateDecl>(
229  TST->getTemplateName().getAsTemplateDecl()))
230  Record = TD->getTemplatedDecl();
231  }
232  }
233  if (!Record)
234  continue;
235  if (auto Search =
236  findDeclInBases(*Record, DeclName, AggressiveTemplateLookup)) {
237  if (*Search) {
238  if (Found)
239  return NameLookup(
240  llvm::None); // Multiple decls found in different base classes.
241  Found = *Search;
242  continue;
243  }
244  } else
245  return NameLookup(llvm::None); // Propagate multiple resolution back up.
246  }
247  return NameLookup(Found); // If nullptr, decl wasnt found.
248 }
249 
250 void RenamerClangTidyCheck::check(const MatchFinder::MatchResult &Result) {
251  if (const auto *Decl =
252  Result.Nodes.getNodeAs<CXXConstructorDecl>("classRef")) {
253 
254  addUsage(Decl->getParent(), Decl->getNameInfo().getSourceRange(),
255  Result.SourceManager);
256 
257  for (const auto *Init : Decl->inits()) {
258  if (!Init->isWritten() || Init->isInClassMemberInitializer())
259  continue;
260  if (const FieldDecl *FD = Init->getAnyMember())
261  addUsage(FD, SourceRange(Init->getMemberLocation()),
262  Result.SourceManager);
263  // Note: delegating constructors and base class initializers are handled
264  // via the "typeLoc" matcher.
265  }
266  return;
267  }
268 
269  if (const auto *Decl =
270  Result.Nodes.getNodeAs<CXXDestructorDecl>("classRef")) {
271 
272  SourceRange Range = Decl->getNameInfo().getSourceRange();
273  if (Range.getBegin().isInvalid())
274  return;
275  // The first token that will be found is the ~ (or the equivalent trigraph),
276  // we want instead to replace the next token, that will be the identifier.
277  Range.setBegin(CharSourceRange::getTokenRange(Range).getEnd());
278 
279  addUsage(Decl->getParent(), Range, Result.SourceManager);
280  return;
281  }
282 
283  if (const auto *Loc = Result.Nodes.getNodeAs<TypeLoc>("typeLoc")) {
284  UnqualTypeLoc Unqual = Loc->getUnqualifiedLoc();
285  NamedDecl *Decl = nullptr;
286  if (const auto &Ref = Unqual.getAs<TagTypeLoc>())
287  Decl = Ref.getDecl();
288  else if (const auto &Ref = Unqual.getAs<InjectedClassNameTypeLoc>())
289  Decl = Ref.getDecl();
290  else if (const auto &Ref = Unqual.getAs<UnresolvedUsingTypeLoc>())
291  Decl = Ref.getDecl();
292  else if (const auto &Ref = Unqual.getAs<TemplateTypeParmTypeLoc>())
293  Decl = Ref.getDecl();
294  // further TypeLocs handled below
295 
296  if (Decl) {
297  addUsage(Decl, Loc->getSourceRange(), Result.SourceManager);
298  return;
299  }
300 
301  if (const auto &Ref = Loc->getAs<TemplateSpecializationTypeLoc>()) {
302  const TemplateDecl *Decl =
303  Ref.getTypePtr()->getTemplateName().getAsTemplateDecl();
304 
305  SourceRange Range(Ref.getTemplateNameLoc(), Ref.getTemplateNameLoc());
306  if (const auto *ClassDecl = dyn_cast<TemplateDecl>(Decl)) {
307  if (const NamedDecl *TemplDecl = ClassDecl->getTemplatedDecl())
308  addUsage(TemplDecl, Range, Result.SourceManager);
309  return;
310  }
311  }
312 
313  if (const auto &Ref =
314  Loc->getAs<DependentTemplateSpecializationTypeLoc>()) {
315  if (const TagDecl *Decl = Ref.getTypePtr()->getAsTagDecl())
316  addUsage(Decl, Loc->getSourceRange(), Result.SourceManager);
317  return;
318  }
319  }
320 
321  if (const auto *Loc =
322  Result.Nodes.getNodeAs<NestedNameSpecifierLoc>("nestedNameLoc")) {
323  if (const NestedNameSpecifier *Spec = Loc->getNestedNameSpecifier()) {
324  if (const NamespaceDecl *Decl = Spec->getAsNamespace()) {
325  addUsage(Decl, Loc->getLocalSourceRange(), Result.SourceManager);
326  return;
327  }
328  }
329  }
330 
331  if (const auto *Decl = Result.Nodes.getNodeAs<UsingDecl>("using")) {
332  for (const auto *Shadow : Decl->shadows())
333  addUsage(Shadow->getTargetDecl(), Decl->getNameInfo().getSourceRange(),
334  Result.SourceManager);
335  return;
336  }
337 
338  if (const auto *DeclRef = Result.Nodes.getNodeAs<DeclRefExpr>("declRef")) {
339  SourceRange Range = DeclRef->getNameInfo().getSourceRange();
340  addUsage(DeclRef->getDecl(), Range, Result.SourceManager);
341  return;
342  }
343 
344  if (const auto *MemberRef =
345  Result.Nodes.getNodeAs<MemberExpr>("memberExpr")) {
346  SourceRange Range = MemberRef->getMemberNameInfo().getSourceRange();
347  addUsage(MemberRef->getMemberDecl(), Range, Result.SourceManager);
348  return;
349  }
350 
351  if (const auto *DepMemberRef =
352  Result.Nodes.getNodeAs<CXXDependentScopeMemberExpr>(
353  "depMemberExpr")) {
354  QualType BaseType = DepMemberRef->isArrow()
355  ? DepMemberRef->getBaseType()->getPointeeType()
356  : DepMemberRef->getBaseType();
357  if (BaseType.isNull())
358  return;
359  const CXXRecordDecl *Base = BaseType.getTypePtr()->getAsCXXRecordDecl();
360  if (!Base)
361  return;
362  DeclarationName DeclName = DepMemberRef->getMemberNameInfo().getName();
363  if (!DeclName.isIdentifier())
364  return;
365  StringRef DependentName = DeclName.getAsIdentifierInfo()->getName();
366 
367  if (NameLookup Resolved = findDeclInBases(
368  *Base, DependentName, AggressiveDependentMemberLookup)) {
369  if (*Resolved)
370  addUsage(*Resolved, DepMemberRef->getMemberNameInfo().getSourceRange(),
371  Result.SourceManager);
372  }
373  return;
374  }
375 
376  if (const auto *Decl = Result.Nodes.getNodeAs<NamedDecl>("decl")) {
377  // Fix using namespace declarations.
378  if (const auto *UsingNS = dyn_cast<UsingDirectiveDecl>(Decl))
379  addUsage(UsingNS->getNominatedNamespaceAsWritten(),
380  UsingNS->getIdentLocation(), Result.SourceManager);
381 
382  if (!Decl->getIdentifier() || Decl->getName().empty() || Decl->isImplicit())
383  return;
384 
385  const auto *Canonical = cast<NamedDecl>(Decl->getCanonicalDecl());
386  if (Canonical != Decl) {
387  addUsage(Canonical, Decl->getLocation(), Result.SourceManager);
388  return;
389  }
390 
391  // Fix type aliases in value declarations.
392  if (const auto *Value = Result.Nodes.getNodeAs<ValueDecl>("decl")) {
393  if (const Type *TypePtr = Value->getType().getTypePtrOrNull()) {
394  if (const auto *Typedef = TypePtr->getAs<TypedefType>())
395  addUsage(Typedef->getDecl(), Value->getSourceRange(),
396  Result.SourceManager);
397  }
398  }
399 
400  // Fix type aliases in function declarations.
401  if (const auto *Value = Result.Nodes.getNodeAs<FunctionDecl>("decl")) {
402  if (const auto *Typedef =
403  Value->getReturnType().getTypePtr()->getAs<TypedefType>())
404  addUsage(Typedef->getDecl(), Value->getSourceRange(),
405  Result.SourceManager);
406  for (const ParmVarDecl *Param : Value->parameters()) {
407  if (const TypedefType *Typedef =
408  Param->getType().getTypePtr()->getAs<TypedefType>())
409  addUsage(Typedef->getDecl(), Value->getSourceRange(),
410  Result.SourceManager);
411  }
412  }
413 
414  // Ignore ClassTemplateSpecializationDecl which are creating duplicate
415  // replacements with CXXRecordDecl.
416  if (isa<ClassTemplateSpecializationDecl>(Decl))
417  return;
418 
419  Optional<FailureInfo> MaybeFailure =
420  GetDeclFailureInfo(Decl, *Result.SourceManager);
421  if (!MaybeFailure)
422  return;
423  FailureInfo &Info = *MaybeFailure;
424  NamingCheckFailure &Failure = NamingCheckFailures[NamingCheckId(
425  Decl->getLocation(), Decl->getNameAsString())];
426  SourceRange Range =
427  DeclarationNameInfo(Decl->getDeclName(), Decl->getLocation())
428  .getSourceRange();
429 
430  const IdentifierTable &Idents = Decl->getASTContext().Idents;
431  auto CheckNewIdentifier = Idents.find(Info.Fixup);
432  if (CheckNewIdentifier != Idents.end()) {
433  const IdentifierInfo *Ident = CheckNewIdentifier->second;
434  if (Ident->isKeyword(getLangOpts()))
436  else if (Ident->hasMacroDefinition())
438  }
439 
440  Failure.Info = std::move(Info);
441  addUsage(Decl, Range);
442  }
443 }
444 
446  const Token &MacroNameTok,
447  const MacroInfo *MI) {
448  Optional<FailureInfo> MaybeFailure =
449  GetMacroFailureInfo(MacroNameTok, SourceMgr);
450  if (!MaybeFailure)
451  return;
452  FailureInfo &Info = *MaybeFailure;
453  StringRef Name = MacroNameTok.getIdentifierInfo()->getName();
454  NamingCheckId ID(MI->getDefinitionLoc(), std::string(Name));
455  NamingCheckFailure &Failure = NamingCheckFailures[ID];
456  SourceRange Range(MacroNameTok.getLocation(), MacroNameTok.getEndLoc());
457 
458  Failure.Info = std::move(Info);
459  addUsage(ID, Range);
460 }
461 
462 void RenamerClangTidyCheck::expandMacro(const Token &MacroNameTok,
463  const MacroInfo *MI) {
464  StringRef Name = MacroNameTok.getIdentifierInfo()->getName();
465  NamingCheckId ID(MI->getDefinitionLoc(), std::string(Name));
466 
467  auto Failure = NamingCheckFailures.find(ID);
468  if (Failure == NamingCheckFailures.end())
469  return;
470 
471  SourceRange Range(MacroNameTok.getLocation(), MacroNameTok.getEndLoc());
472  addUsage(ID, Range);
473 }
474 
475 static std::string
477  const std::string &Fixup) {
478  if (Fixup.empty())
479  return "; cannot be fixed automatically";
481  return {};
482  if (FixStatus >=
484  return {};
486  return "; cannot be fixed because '" + Fixup +
487  "' would conflict with a keyword";
488  if (FixStatus ==
490  return "; cannot be fixed because '" + Fixup +
491  "' would conflict with a macro definition";
492 
493  llvm_unreachable("invalid ShouldFixStatus");
494 }
495 
497  for (const auto &Pair : NamingCheckFailures) {
498  const NamingCheckId &Decl = Pair.first;
499  const NamingCheckFailure &Failure = Pair.second;
500 
501  if (Failure.Info.KindName.empty())
502  continue;
503 
504  if (Failure.ShouldNotify()) {
505  auto DiagInfo = GetDiagInfo(Decl, Failure);
506  auto Diag = diag(Decl.first,
508  Failure.Info.Fixup));
509  DiagInfo.ApplyArgs(Diag);
510 
511  if (Failure.ShouldFix()) {
512  for (const auto &Loc : Failure.RawUsageLocs) {
513  // We assume that the identifier name is made of one token only. This
514  // is always the case as we ignore usages in macros that could build
515  // identifier names by combining multiple tokens.
516  //
517  // For destructors, we already take care of it by remembering the
518  // location of the start of the identifier and not the start of the
519  // tilde.
520  //
521  // Other multi-token identifiers, such as operators are not checked at
522  // all.
523  Diag << FixItHint::CreateReplacement(
524  SourceRange(SourceLocation::getFromRawEncoding(Loc)),
525  Failure.Info.Fixup);
526  }
527  }
528  }
529  }
530 }
531 
532 } // namespace tidy
533 } // namespace clang
virtual DiagInfo GetDiagInfo(const NamingCheckId &ID, const NamingCheckFailure &Failure) const =0
Overridden by derived classes, returns a description of the diagnostic that should be emitted for the...
SourceLocation Loc
&#39;#&#39; location in the include directive
void expandMacro(const Token &MacroNameTok, const MacroInfo *MI)
Add a usage of a macro if it already has a violation.
const FunctionDecl * Decl
bool ShouldFix() const
Whether the failure should be fixed or not.
Some operations such as code completion produce a set of candidates.
const Node * Parent
virtual llvm::Optional< FailureInfo > GetDeclFailureInfo(const NamedDecl *Decl, const SourceManager &SM) const =0
Overridden by derived classes, returns information about if and how a Decl failed the check...
llvm::SmallVector< uint64_t, 1024 > Record
Information describing a failed check.
llvm::SourceMgr * SourceMgr
Represents customized diagnostic text and how arguments should be applied.
std::pair< SourceLocation, std::string > NamingCheckId
Base class for all clang-tidy checks.
void addUsage(const RenamerClangTidyCheck::NamingCheckId &Decl, SourceRange Range, SourceManager *SourceMgr=nullptr)
const LangOptions & getLangOpts() const
Returns the language options from the context.
llvm::DenseSet< unsigned > RawUsageLocs
A set of all the identifier usages starting SourceLocation, in their encoded form.
Values pass this threshold will be ignored completely i.e no message, no fixup.
static bool isEqual(const NamingCheckId &LHS, const NamingCheckId &RHS)
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
virtual llvm::Optional< FailureInfo > GetMacroFailureInfo(const Token &MacroNameTok, const SourceManager &SM) const =0
Overridden by derived classes, returns information about if and how a macro failed the check...
If the identifier was used or declared within a macro we won&#39;t offer a fixup for safety reasons...
static std::string getDiagnosticSuffix(const RenamerClangTidyCheck::ShouldFixStatus FixStatus, const std::string &Fixup)
llvm::unique_function< void(DiagnosticBuilder &)> ApplyArgs
static constexpr llvm::StringLiteral Name
void check(const ast_matchers::MatchFinder::MatchResult &Result) override final
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Derived classes that override this function should call this method from the overridden method...
Holds an identifier name check failure, tracking the kind of the identifier, its possible fixup and t...
FunctionInfo Info
The fixup will conflict with a language keyword, so we can&#39;t fix it automatically.
The fixup will conflict with a macro definition, so we can&#39;t fix it automatically.
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override final
Override this to register PPCallbacks in the preprocessor.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
const NamedDecl * findDecl(const RecordDecl &RecDecl, StringRef DeclName)
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
void checkMacro(SourceManager &sourceMgr, const Token &MacroNameTok, const MacroInfo *MI)
Check Macros for style violations.
CharSourceRange Range
SourceRange for the file name.
bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM)
Definition: ASTUtils.cpp:90
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
ShouldFixStatus
This enum will be used in select of the diagnostic message.
std::unique_ptr< GlobalCompilationDatabase > Base
void registerMatchers(ast_matchers::MatchFinder *Finder) override final
Derived classes should not implement any matching logic themselves; this class will do the matching a...
std::map< std::string, ClangTidyValue > OptionMap
const DeclRefExpr * DeclRef
NodeType Type
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check&#39;s name.
NameLookup findDeclInBases(const CXXRecordDecl &Parent, StringRef DeclName, bool AggressiveTemplateLookup)
Returns a decl matching the DeclName in Parent or one of its base classes.