38 namedDecl(anyOf(varDecl(unless(isDefinition())),
39 functionDecl(unless(anyOf(
40 isDefinition(), isDefaulted(),
41 doesDeclarationForceExternallyVisibleDefinition(),
42 hasAncestor(friendDecl()))))),
43 optionally(hasParent(linkageSpecDecl().bind(
"extern"))))
49 const auto *D = Result.Nodes.getNodeAs<NamedDecl>(
"Decl");
50 const auto *Prev = D->getPreviousDecl();
53 if (!Prev->getLocation().isValid())
55 if (Prev->getLocation() == D->getLocation())
58 (D->getLocation().isMacroID() || Prev->getLocation().isMacroID()))
61 for (
const auto &Parent : Result.Context->getParents(*Prev))
62 if (Parent.get<FriendDecl>())
65 const SourceManager &SM = *Result.SourceManager;
67 const bool DifferentHeaders =
68 !SM.isInMainFile(D->getLocation()) &&
69 !SM.isWrittenInSameFile(Prev->getLocation(), D->getLocation());
71 bool MultiVar =
false;
72 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
74 for (
const auto *Other : VD->getDeclContext()->decls()) {
75 if (Other != D && Other->getBeginLoc() == VD->getBeginLoc()) {
82 SourceLocation EndLoc = Lexer::getLocForEndOfToken(
83 D->getSourceRange().getEnd(), 0, SM, Result.Context->getLangOpts());
85 auto Diag = diag(D->getLocation(),
"redundant %0 declaration") << D;
86 if (!MultiVar && !DifferentHeaders) {
87 SourceLocation BeginLoc;
88 if (
const auto *Extern =
89 Result.Nodes.getNodeAs<LinkageSpecDecl>(
"extern");
90 Extern && !Extern->hasBraces())
91 BeginLoc = Extern->getExternLoc();
93 BeginLoc = D->getSourceRange().getBegin();
95 Diag << FixItHint::CreateRemoval(SourceRange(BeginLoc, EndLoc));
98 diag(Prev->getLocation(),
"previously declared here", DiagnosticIDs::Note);
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.