Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -19,6 +19,7 @@ ReadabilityTidyModule.cpp RedundantControlFlowCheck.cpp RedundantDeclarationCheck.cpp + RedundantExternCheck.cpp RedundantFunctionPtrDereferenceCheck.cpp RedundantMemberInitCheck.cpp RedundantStringCStrCheck.cpp Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -27,6 +27,7 @@ #include "RedundantControlFlowCheck.h" #include "RedundantDeclarationCheck.h" #include "RedundantFunctionPtrDereferenceCheck.h" +#include "RedundantExternCheck.h" #include "RedundantMemberInitCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" @@ -69,6 +70,8 @@ "readability-misleading-indentation"); CheckFactories.registerCheck( "readability-misplaced-array-index"); + CheckFactories.registerCheck( + "readability-redundant-extern"); CheckFactories.registerCheck( "readability-redundant-function-ptr-dereference"); CheckFactories.registerCheck( Index: clang-tidy/readability/RedundantExternCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/RedundantExternCheck.h @@ -0,0 +1,35 @@ +//===--- RedundantExternCheck.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_EXTERN_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_EXTERN_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Finds redundant 'extern' keywords +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-extern.html +class RedundantExternCheck : public ClangTidyCheck { +public: + RedundantExternCheck(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_EXTERN_H Index: clang-tidy/readability/RedundantExternCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/RedundantExternCheck.cpp @@ -0,0 +1,54 @@ +//===--- RedundantExternCheck.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 "RedundantExternCheck.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 RedundantExternCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + functionDecl(unless(isExternC())).bind("redundant_extern"), + this); +} + +void RedundantExternCheck::check(const MatchFinder::MatchResult &Result) { + auto* FD = + Result.Nodes.getNodeAs("redundant_extern"); + SourceLocation BeginLoc = FD->getLocStart(); + SourceLocation EndLoc = FD->getLocEnd(); + + if(!(FD->getStorageClass() == SC_Extern)) + return; + + auto Diag = diag(FD->getLocStart(), "redundant 'extern' keyword"); + + if (FD->getLocStart().isMacroID()) + return; + + StringRef Text = + Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc), + *Result.SourceManager, getLangOpts()); + + int offset = Text.find("extern"); + + Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange( + BeginLoc.getLocWithOffset(offset), + BeginLoc.getLocWithOffset(offset + strlen("extern")))); +} + +} // namespace readability +} // namespace tidy +} // namespace clang \ No newline at end of file Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -224,6 +224,7 @@ readability-non-const-parameter readability-redundant-control-flow readability-redundant-declaration + readability-redundant-extern readability-redundant-function-ptr-dereference readability-redundant-member-init readability-redundant-smartptr-get Index: docs/clang-tidy/checks/readability-redundant-extern.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/readability-redundant-extern.rst @@ -0,0 +1,13 @@ +.. title:: clang-tidy - readability-redundant-extern + +readability-redundant-extern +============================= + +This checker removes the redundant `extern` keywords from code. + +`extern` is redundant in function declarations + +.. code-block:: c++ + + extern void h(); + \ No newline at end of file Index: test/clang-tidy/readability-redundant-extern.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-redundant-extern.cpp @@ -0,0 +1,33 @@ +// RUN: %check_clang_tidy %s readability-redundant-extern %t + +extern int f(); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: redundant 'extern' keyword [readability-redundant-extern] +// CHECK-FIXES: int f(); + +extern int f() { return 0; } +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: redundant 'extern' keyword [readability-redundant-extern] +// CHECK-FIXES: int f() { return 0; } + +extern "C" int g(); + +extern "C" int g() { return 0; } + +extern "C++" int h(); + +extern "C++" int h() { return 0; } + +inline extern void foo_inline(); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: redundant 'extern' keyword [readability-redundant-extern] +// CHECK-FIXES: inline void foo_inline(); + +#define FOO_EXTERN extern +FOO_EXTERN void foo_macro_1(); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: redundant 'extern' keyword [readability-redundant-extern] + +#define FOO_INLINE inline +FOO_INLINE extern void foo_macro_3(); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: redundant 'extern' keyword [readability-redundant-extern] + +#define FOO_EXTERN_INLINE inline extern +FOO_EXTERN_INLINE void foo_macro_2(); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: redundant 'extern' keyword [readability-redundant-extern]