Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -11,6 +11,7 @@ NamedParameterCheck.cpp NamespaceCommentCheck.cpp ReadabilityTidyModule.cpp + RedundantReturnCheck.cpp RedundantStringCStrCheck.cpp RedundantSmartptrGetCheck.cpp SimplifyBooleanExprCheck.cpp Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -18,6 +18,7 @@ #include "ImplicitBoolCastCheck.h" #include "InconsistentDeclarationParameterNameCheck.h" #include "NamedParameterCheck.h" +#include "RedundantReturnCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" #include "SimplifyBooleanExprCheck.h" @@ -44,6 +45,8 @@ "readability-implicit-bool-cast"); CheckFactories.registerCheck( "readability-inconsistent-declaration-parameter-name"); + CheckFactories.registerCheck( + "readability-redundant-return"); CheckFactories.registerCheck( "readability-uniqueptr-delete-release"); CheckFactories.registerCheck( Index: clang-tidy/readability/RedundantReturnCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/RedundantReturnCheck.h @@ -0,0 +1,36 @@ +//===--- RedundantReturnCheck.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_RETURN_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_RETURN_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Eliminates redundant `return` statements at the end of a function that +/// returns `void`. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-return.html +class RedundantReturnCheck : public ClangTidyCheck { +public: + RedundantReturnCheck(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_RETURN_H Index: clang-tidy/readability/RedundantReturnCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/RedundantReturnCheck.cpp @@ -0,0 +1,60 @@ +//===--- RedundantReturnCheck.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 "RedundantReturnCheck.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 RedundantReturnCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + functionDecl(isDefinition(), returns(asString("void")), + has(compoundStmt(hasAnySubstatement(returnStmt())))) + .bind("fn"), + this); +} + +void RedundantReturnCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Fn = Result.Nodes.getNodeAs("fn"); + if (const auto *Block = dyn_cast(Fn->getBody())) { + CompoundStmt::const_reverse_body_iterator last = Block->body_rbegin(); + if (const auto *Return = dyn_cast(*last)) { + CompoundStmt::const_reverse_body_iterator Previous = + ++Block->body_rbegin(); + SourceLocation Start; + if (Previous != Block->body_rend()) { + Start = Lexer::findLocationAfterToken( + dyn_cast(*Previous)->getLocEnd(), tok::semi, + *Result.SourceManager, Result.Context->getLangOpts(), + /*SkipTrailingWhitespaceAndNewLine=*/true); + } else { + Start = Return->getLocStart(); + } + auto ReturnRange = CharSourceRange::getCharRange( + Start, Lexer::findLocationAfterToken( + Return->getLocEnd(), tok::semi, *Result.SourceManager, + Result.Context->getLangOpts(), + /*SkipTrailingWhitespaceAndNewLine=*/true)); + + diag(Return->getLocStart(), + "redundant return statement at the end of void function") + << FixItHint::CreateRemoval(ReturnRange); + } + } +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -76,6 +76,7 @@ readability-implicit-bool-cast readability-inconsistent-declaration-parameter-name readability-named-parameter + readability-redundant-return readability-redundant-smartptr-get readability-redundant-string-cstr readability-simplify-boolean-expr Index: docs/clang-tidy/checks/readability-redundant-return.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/readability-redundant-return.rst @@ -0,0 +1,7 @@ +.. title:: clang-tidy - readability-redundant-return + +readability-redundant-return +============================ + +This check looks for procedures (functions returning no value) with return +statements at the end of the function. Such return statements are redundant. Index: test/clang-tidy/readability-redundant-return.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-redundant-return.cpp @@ -0,0 +1,41 @@ +// RUN: %check_clang_tidy %s readability-redundant-return %t + +void g(int i); +void j(); + +void f() +{ + return; +} +// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement at the end of void function [readability-redundant-return] +// CHECK-FIXES: {{^}}void f(){{$}} +// CHECK-FIXES-NEXT: {{^{$}} +// CHECK-FIXES-NEXT: {{^ *}$}} + +void g() +{ + f(); + return; +} +// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement +// CHECK-FIXES: {{^ }}f();{{$}} +// CHECK-FIXES-NEXT: {{^ *}$}} + +void g(int i) +{ + if (i < 0) { + return; + } + if (i < 10) { + f(); + } +} + +int h() +{ + return 1; +} + +void j() +{ +}