summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp
diff options
context:
space:
mode:
authorDaniel Marjamaki <daniel.marjamaki@evidente.se>2016-11-01 13:26:15 +0000
committerDaniel Marjamaki <daniel.marjamaki@evidente.se>2016-11-01 13:26:15 +0000
commit399a50cf356f4881cbab46a95d2c9efed18454ba (patch)
tree810df5388c966a3e8535a71dd7dd31cdb5a7b5ea /clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp
parent62f516f5906f967179610a73e4cc1d852b908bbd (diff)
downloadbcm5719-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.cpp71
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
OpenPOWER on IntegriCloud