10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 12 #include "clang/Lex/Lexer.h" 18 namespace readability {
20 AST_MATCHER(FunctionDecl, doesDeclarationForceExternallyVisibleDefinition) {
21 return Node.doesDeclarationForceExternallyVisibleDefinition();
24 RedundantDeclarationCheck::RedundantDeclarationCheck(StringRef
Name,
27 IgnoreMacros(Options.getLocalOrGlobal(
"IgnoreMacros", true)) {}
31 namedDecl(anyOf(varDecl(unless(isDefinition())),
32 functionDecl(unless(anyOf(
33 isDefinition(), isDefaulted(),
34 doesDeclarationForceExternallyVisibleDefinition(),
35 hasParent(friendDecl()))))))
41 const auto *D = Result.Nodes.getNodeAs<NamedDecl>(
"Decl");
42 const auto *Prev = D->getPreviousDecl();
45 if (!Prev->getLocation().isValid())
47 if (Prev->getLocation() == D->getLocation())
50 (D->getLocation().isMacroID() || Prev->getLocation().isMacroID()))
53 for (
const auto &
Parent : Result.Context->getParents(*Prev))
54 if (
Parent.get<FriendDecl>())
57 const SourceManager &SM = *Result.SourceManager;
59 const bool DifferentHeaders =
60 !SM.isInMainFile(D->getLocation()) &&
61 !SM.isWrittenInSameFile(Prev->getLocation(), D->getLocation());
63 bool MultiVar =
false;
64 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
66 for (
const auto Other : VD->getDeclContext()->decls()) {
67 if (Other != D && Other->getBeginLoc() == VD->getBeginLoc()) {
74 SourceLocation EndLoc = Lexer::getLocForEndOfToken(
75 D->getSourceRange().getEnd(), 0, SM, Result.Context->getLangOpts());
77 auto Diag =
diag(D->getLocation(),
"redundant %0 declaration") << D;
78 if (!MultiVar && !DifferentHeaders)
79 Diag << FixItHint::CreateRemoval(
80 SourceRange(D->getSourceRange().getBegin(), EndLoc));
82 diag(Prev->getLocation(),
"previously declared here", DiagnosticIDs::Note);
AST_MATCHER(Expr, isMacroID)
Base class for all clang-tidy checks.
static constexpr llvm::StringLiteral Name
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.