[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
This commit is contained in:
Daniel Marjamaki 2016-11-01 13:26:15 +00:00
parent 62f516f590
commit 399a50cf35
8 changed files with 166 additions and 0 deletions

View File

@ -16,6 +16,7 @@ add_clang_library(clangTidyReadabilityModule
NonConstParameterCheck.cpp
ReadabilityTidyModule.cpp
RedundantControlFlowCheck.cpp
RedundantDeclarationCheck.cpp
RedundantMemberInitCheck.cpp
RedundantStringCStrCheck.cpp
RedundantSmartptrGetCheck.cpp

View File

@ -23,6 +23,7 @@
#include "NamedParameterCheck.h"
#include "NonConstParameterCheck.h"
#include "RedundantControlFlowCheck.h"
#include "RedundantDeclarationCheck.h"
#include "RedundantMemberInitCheck.h"
#include "RedundantSmartptrGetCheck.h"
#include "RedundantStringCStrCheck.h"
@ -68,6 +69,8 @@ public:
"readability-non-const-parameter");
CheckFactories.registerCheck<RedundantControlFlowCheck>(
"readability-redundant-control-flow");
CheckFactories.registerCheck<RedundantDeclarationCheck>(
"readability-redundant-declaration");
CheckFactories.registerCheck<RedundantSmartptrGetCheck>(
"readability-redundant-smartptr-get");
CheckFactories.registerCheck<RedundantStringCStrCheck>(

View File

@ -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

View File

@ -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

View File

@ -129,6 +129,11 @@ Improvements to clang-tidy
Flags member initializations that are unnecessary because the same default
constructor would be called if they were not present.
- New `readability-redundant-declaration
<http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-declaration.html>`_ check
Warns about duplicate variable declarations.
Fixed bugs:
- `modernize-make-unique

View File

@ -133,6 +133,7 @@ Clang-Tidy Checks
readability-named-parameter
readability-non-const-parameter
readability-redundant-control-flow
readability-redundant-declaration
readability-redundant-member-init
readability-redundant-smartptr-get
readability-redundant-string-cstr

View File

@ -0,0 +1,27 @@
.. title:: clang-tidy - readability-redundant-declaration
readability-redundant-declaration
=================================
Finds redundant variable and function declarations.
.. code-block:: c++
extern int X;
extern int X;
becomes
.. code-block:: c++
extern int X;
Such redundant declarations can be removed without changing program behaviour.
They can for instance be unintentional left overs from previous refactorings
when code has been moved around. Having redundant declarations could in worst
case mean that there are typos in the code that cause bugs.
Normally the code can be automatically fixed, clang-tidy can remove the second
declaration. However there are 2 cases when you need to fix the code manually:
* When the declarations are in different header files.
* When multiple variables are declared together.

View File

@ -0,0 +1,23 @@
// RUN: %check_clang_tidy %s readability-redundant-declaration %t
extern int Xyz;
extern int Xyz;
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Xyz' declaration [readability-redundant-declaration]
// CHECK-FIXES: {{^}}{{$}}
int Xyz = 123;
extern int A;
extern int A, B;
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'A' declaration
// CHECK-FIXES: {{^}}extern int A, B;{{$}}
extern int Buf[10];
extern int Buf[10];
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Buf' declaration
// CHECK-FIXES: {{^}}{{$}}
static int f();
static int f();
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'f' declaration
// CHECK-FIXES: {{^}}{{$}}
static int f() {}