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