clang-tools  4.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 
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 void RedundantDeclarationCheck::registerMatchers(MatchFinder *Finder) {
22  Finder->addMatcher(namedDecl(anyOf(varDecl(), functionDecl())).bind("Decl"),
23  this);
24 }
25 
26 void RedundantDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
27  const auto *D = Result.Nodes.getNodeAs<NamedDecl>("Decl");
28  const auto *Prev = D->getPreviousDecl();
29  if (!Prev)
30  return;
31  if (!Prev->getLocation().isValid())
32  return;
33  if (Prev->getLocation() == D->getLocation())
34  return;
35 
36  const SourceManager &SM = *Result.SourceManager;
37 
38  const bool DifferentHeaders =
39  !SM.isInMainFile(D->getLocation()) &&
40  !SM.isWrittenInSameFile(Prev->getLocation(), D->getLocation());
41 
42  bool MultiVar = false;
43  if (const auto *VD = dyn_cast<VarDecl>(D)) {
44  if (VD->getPreviousDecl()->getStorageClass() == SC_Extern &&
45  VD->getStorageClass() != SC_Extern)
46  return;
47  // Is this a multivariable declaration?
48  for (const auto Other : VD->getDeclContext()->decls()) {
49  if (Other != D && Other->getLocStart() == VD->getLocStart()) {
50  MultiVar = true;
51  break;
52  }
53  }
54  } else {
55  const auto *FD = cast<FunctionDecl>(D);
56  if (FD->isThisDeclarationADefinition())
57  return;
58  }
59 
60  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
61  D->getSourceRange().getEnd(), 0, SM, Result.Context->getLangOpts());
62  {
63  auto Diag = diag(D->getLocation(), "redundant %0 declaration") << D;
64  if (!MultiVar && !DifferentHeaders)
65  Diag << FixItHint::CreateRemoval(
66  SourceRange(D->getSourceRange().getBegin(), EndLoc));
67  }
68  diag(Prev->getLocation(), "previously declared here", DiagnosticIDs::Note);
69 }
70 
71 } // namespace readability
72 } // namespace tidy
73 } // namespace clang
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:262
SourceManager & SM
const NamedDecl * Result
Definition: USRFinder.cpp:162