Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -16,6 +16,7 @@ NonConstParameterCheck.cpp ReadabilityTidyModule.cpp RedundantControlFlowCheck.cpp + RedundantDeclarationCheck.cpp RedundantStringCStrCheck.cpp RedundantSmartptrGetCheck.cpp RedundantStringInitCheck.cpp Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -23,6 +23,7 @@ #include "NamedParameterCheck.h" #include "NonConstParameterCheck.h" #include "RedundantControlFlowCheck.h" +#include "RedundantDeclarationCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" #include "RedundantStringInitCheck.h" @@ -57,6 +58,8 @@ "readability-inconsistent-declaration-parameter-name"); CheckFactories.registerCheck( "readability-misplaced-array-index"); + CheckFactories.registerCheck( + "readability-redundant-declaration"); CheckFactories.registerCheck( "readability-static-definition-in-anonymous-namespace"); CheckFactories.registerCheck( Index: clang-tidy/readability/RedundantDeclarationCheck.h =================================================================== --- clang-tidy/readability/RedundantDeclarationCheck.h +++ clang-tidy/readability/RedundantDeclarationCheck.h @@ -0,0 +1,35 @@ +//===--- RedundantDeclarationCheck.h - clang-tidy----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_DECLARATION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_DECLARATION_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Find redundant variable declarations. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-declaration.html +class RedundantDeclarationCheck : public ClangTidyCheck { +public: + RedundantDeclarationCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_DECLARATION_H Index: clang-tidy/readability/RedundantDeclarationCheck.cpp =================================================================== --- clang-tidy/readability/RedundantDeclarationCheck.cpp +++ clang-tidy/readability/RedundantDeclarationCheck.cpp @@ -0,0 +1,70 @@ +//===--- 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(varDecl().bind("Decl"), this); +} + +void RedundantDeclarationCheck::check(const MatchFinder::MatchResult &Result) { + const auto *VD = Result.Nodes.getNodeAs("Decl"); + const auto *Prev = VD->getPreviousDecl(); + if (!Prev) + return; + if (Prev->getStorageClass() == SC_Extern && + VD->getStorageClass() != SC_Extern) + return; + if (Prev->getLocation() == VD->getLocation()) + return; + const SourceManager &SM = *Result.SourceManager; + if (SM.isInSystemHeader(VD->getLocation())) + return; + if (!SM.isInMainFile(VD->getLocation()) && + !SM.isWrittenInSameFile(Prev->getLocation(), VD->getLocation())) + return; + + // Don't generate fixits for multivariable declarations. + bool MultiVar = false; + for (const char *Code = SM.getCharacterData(VD->getLocStart()); + *Code && *Code != ';'; ++Code) { + if (*Code == ',') { + MultiVar = true; + break; + } + } + + if (MultiVar) { + diag(VD->getLocation(), "redundant variable %0 declaration") + << VD->getName(); + diag(VD->getPreviousDecl()->getLocation(), "previously declared here", + DiagnosticIDs::Note); + } else { + SourceLocation EndLoc = Lexer::getLocForEndOfToken( + VD->getLocEnd(), 0, SM, Result.Context->getLangOpts()); + diag(VD->getLocation(), "redundant variable %0 declaration") + << VD->getName() + << FixItHint::CreateRemoval(SourceRange(VD->getLocStart(), EndLoc)); + diag(VD->getPreviousDecl()->getLocation(), "previously declared here", + DiagnosticIDs::Note); + } +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -111,6 +111,11 @@ Flags function parameters of a pointer type that could be changed to point to a constant type instead. +- New `readability-redundant-declaration + `_ check + + Warns about duplicate variable declarations. + Fixed bugs: - `modernize-make-unique Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -133,6 +133,7 @@ readability-named-parameter readability-non-const-parameter readability-redundant-control-flow + readability-redundant-declaration readability-redundant-smartptr-get readability-redundant-string-cstr readability-redundant-string-init Index: docs/clang-tidy/checks/readability-redundant-declaration.rst =================================================================== --- docs/clang-tidy/checks/readability-redundant-declaration.rst +++ docs/clang-tidy/checks/readability-redundant-declaration.rst @@ -0,0 +1,17 @@ +.. title:: clang-tidy - readability-redundant-declaration + +readability-redundant-declaration +================================= + +Finds redundant variable declarations. + +.. code-block:: c++ + + extern int X; + extern int X; + +becomes + +.. code-block:: c++ + + extern int X; Index: test/clang-tidy/readability-redundant-declaration.cpp =================================================================== --- test/clang-tidy/readability-redundant-declaration.cpp +++ test/clang-tidy/readability-redundant-declaration.cpp @@ -0,0 +1,16 @@ +// RUN: %check_clang_tidy %s readability-redundant-declaration %t + +extern int Xyz; +extern int Xyz; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant variable Xyz declaration [readability-redundant-declaration] +// CHECK-FIXES: {{^}}{{$}} + +extern int A; +extern int A, B; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant variable A declaration +// CHECK-FIXES: {{^}}extern int A,B;{{$}} + +extern int Buf[10]; +extern int Buf[10]; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant variable Buf declaration +// CHECK-FIXES: {{^}}{{$}}