diff options
| author | Daniel Marjamaki <daniel.marjamaki@evidente.se> | 2016-11-01 13:26:15 +0000 |
|---|---|---|
| committer | Daniel Marjamaki <daniel.marjamaki@evidente.se> | 2016-11-01 13:26:15 +0000 |
| commit | 399a50cf356f4881cbab46a95d2c9efed18454ba (patch) | |
| tree | 810df5388c966a3e8535a71dd7dd31cdb5a7b5ea /clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp | |
| parent | 62f516f5906f967179610a73e4cc1d852b908bbd (diff) | |
| download | bcm5719-llvm-399a50cf356f4881cbab46a95d2c9efed18454ba.tar.gz bcm5719-llvm-399a50cf356f4881cbab46a95d2c9efed18454ba.zip | |
[clang-tidy] Add check readability-redundant-declaration
Finds redundant variable and function declarations.
extern int X;
extern int X; // <- redundant
Differential Revision: https://reviews.llvm.org/D24656
llvm-svn: 285689
Diffstat (limited to 'clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp')
| -rw-r--r-- | clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp new file mode 100644 index 00000000000..44aa7a5a18e --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp @@ -0,0 +1,71 @@ +//===--- RedundantDeclarationCheck.cpp - clang-tidy------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RedundantDeclarationCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +void RedundantDeclarationCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(namedDecl(anyOf(varDecl(), functionDecl())).bind("Decl"), this); +} + +void RedundantDeclarationCheck::check(const MatchFinder::MatchResult &Result) { + const NamedDecl *D = Result.Nodes.getNodeAs<NamedDecl>("Decl"); + const auto *Prev = D->getPreviousDecl(); + if (!Prev) + return; + if (Prev->getLocation() == D->getLocation()) + return; + + const SourceManager &SM = *Result.SourceManager; + + const bool DifferentHeaders = + !SM.isInMainFile(D->getLocation()) && + !SM.isWrittenInSameFile(Prev->getLocation(), D->getLocation()); + + bool MultiVar = false; + if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (VD->getPreviousDecl()->getStorageClass() == SC_Extern && + VD->getStorageClass() != SC_Extern) + return; + // Is this a multivariable declaration? + for (const auto Other : VD->getDeclContext()->decls()) { + if (Other != D && Other->getLocStart() == VD->getLocStart()) { + MultiVar = true; + break; + } + } + } else { + const auto *FD = cast<FunctionDecl>(D); + if (FD->isThisDeclarationADefinition()) + return; + } + + SourceLocation EndLoc = Lexer::getLocForEndOfToken( + D->getSourceRange().getEnd(), 0, SM, Result.Context->getLangOpts()); + { + auto Diag = diag(D->getLocation(), "redundant %0 declaration") + << D; + if (!MultiVar && !DifferentHeaders) + Diag << FixItHint::CreateRemoval( + SourceRange(D->getSourceRange().getBegin(), EndLoc)); + } + diag(Prev->getLocation(), "previously declared here", DiagnosticIDs::Note); +} + +} // namespace readability +} // namespace tidy +} // namespace clang |

