clang-tools 6.0.0

RedundantDeclarationCheck.cpp
Go to the documentation of this file.
1 //===--- RedundantDeclarationCheck.cpp - clang-tidy------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "RedundantDeclarationCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14
15 using namespace clang::ast_matchers;
16
17 namespace clang {
18 namespace tidy {
19 namespace readability {
20
21 RedundantDeclarationCheck::RedundantDeclarationCheck(StringRef Name,
22 ClangTidyContext *Context)
23 : ClangTidyCheck(Name, Context),
24 IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
25
26 void RedundantDeclarationCheck::registerMatchers(MatchFinder *Finder) {
27 Finder->addMatcher(
28 namedDecl(anyOf(varDecl(unless(isDefinition())),
29 functionDecl(unless(anyOf(isDefinition(), isDefaulted(),
30 hasParent(friendDecl()))))))
31 .bind("Decl"),
32 this);
33 }
34
35 void RedundantDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
36 const auto *D = Result.Nodes.getNodeAs<NamedDecl>("Decl");
37 const auto *Prev = D->getPreviousDecl();
38 if (!Prev)
39 return;
40 if (!Prev->getLocation().isValid())
41 return;
42 if (Prev->getLocation() == D->getLocation())
43 return;
44 if (IgnoreMacros &&
45 (D->getLocation().isMacroID() || Prev->getLocation().isMacroID()))
46 return;
47 // Don't complain when the previous declaration is a friend declaration.
48 for (const auto &Parent : Result.Context->getParents(*Prev))
49 if (Parent.get<FriendDecl>())
50 return;
51
52 const SourceManager &SM = *Result.SourceManager;
53
54 const bool DifferentHeaders =
55 !SM.isInMainFile(D->getLocation()) &&
56 !SM.isWrittenInSameFile(Prev->getLocation(), D->getLocation());
57
58 bool MultiVar = false;
59 if (const auto *VD = dyn_cast<VarDecl>(D)) {
60 // Is this a multivariable declaration?
61 for (const auto Other : VD->getDeclContext()->decls()) {
62 if (Other != D && Other->getLocStart() == VD->getLocStart()) {
63 MultiVar = true;
64 break;
65 }
66 }
67 }
68
69 SourceLocation EndLoc = Lexer::getLocForEndOfToken(
70 D->getSourceRange().getEnd(), 0, SM, Result.Context->getLangOpts());
71 {
72 auto Diag = diag(D->getLocation(), "redundant %0 declaration") << D;
73 if (!MultiVar && !DifferentHeaders)
74 Diag << FixItHint::CreateRemoval(
75 SourceRange(D->getSourceRange().getBegin(), EndLoc));
76 }
77 diag(Prev->getLocation(), "previously declared here", DiagnosticIDs::Note);
78 }
79
80 } // namespace readability
81 } // namespace tidy
82 } // namespace clang
clang::ast_matchers
Definition: ClangTidyDiagnosticConsumer.h:27
Name
StringHandle Name
Definition: PreprocessorTracker.cpp:525
clang::tidy::ClangTidyCheck
Base class for all clang-tidy checks.
Definition: ClangTidy.h:127
clang
Definition: AndroidTidyModule.cpp:28
clang::tidy::readability::RedundantDeclarationCheck::check
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
Definition: RedundantDeclarationCheck.cpp:35
RedundantDeclarationCheck.h
clang::tidy::ClangTidyContext
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
Definition: ClangTidyDiagnosticConsumer.h:104
clang::tidy::ClangTidyCheck::diag
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check&#39;s name.
Definition: ClangTidy.cpp:416
clang::tidy::readability::RedundantDeclarationCheck::registerMatchers
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
Definition: RedundantDeclarationCheck.cpp:26