Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -2,6 +2,7 @@ add_clang_library(clangTidyReadabilityModule BracesAroundStatementsCheck.cpp + ElseAfterReturnCheck.cpp FunctionSize.cpp NamespaceCommentCheck.cpp ReadabilityTidyModule.cpp Index: clang-tidy/readability/ElseAfterReturnCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/ElseAfterReturnCheck.h @@ -0,0 +1,30 @@ +//===--- ElseAfterReturnCheck.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_ELSE_AFTER_RETURN_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ELSE_AFTER_RETURN_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { + +class ElseAfterReturnCheck : public ClangTidyCheck { +public: + ElseAfterReturnCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ELSE_AFTER_RETURN_H + Index: clang-tidy/readability/ElseAfterReturnCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/ElseAfterReturnCheck.cpp @@ -0,0 +1,46 @@ +//===--- ElseAfterReturnCheck.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 "ElseAfterReturnCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + ifStmt( + hasThen(stmt(anyOf(returnStmt(), compoundStmt(has(returnStmt()))))), + hasElse(stmt().bind("else"))).bind("if"), + this); +} + +static FixItHint removeToken(SourceLocation Loc) { + return FixItHint::CreateRemoval(CharSourceRange::getTokenRange(Loc, Loc)); +} + +void ElseAfterReturnCheck::check(const MatchFinder::MatchResult &Result) { + const auto *If = Result.Nodes.getNodeAs("if"); + SourceLocation ElseLoc = If->getElseLoc(); + if (ElseLoc.isInvalid()) + If->dump(); + DiagnosticBuilder Diag = diag(ElseLoc, "don't use else after return"); + Diag << removeToken(ElseLoc); + + // FIXME: Removing the braces isn't always safe. Do a more careful analysis. + if (const CompoundStmt *CS = Result.Nodes.getNodeAs("else")) + Diag << removeToken(CS->getLBracLoc()) << removeToken(CS->getRBracLoc()); +} + +} // namespace tidy +} // namespace clang + Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" #include "BracesAroundStatementsCheck.h" +#include "ElseAfterReturnCheck.h" #include "FunctionSize.h" #include "RedundantSmartptrGet.h" @@ -23,6 +24,8 @@ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { CheckFactories.registerCheck( "readability-braces-around-statements"); + CheckFactories.registerCheck( + "readability-else-after-return"); CheckFactories.registerCheck( "readability-function-size"); CheckFactories.registerCheck( Index: test/clang-tidy/readability-else-after-return.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-else-after-return.cpp @@ -0,0 +1,28 @@ +// RUN: $(dirname %s)/check_clang_tidy.sh %s readability-else-after-return %t +// REQUIRES: shell + +void f(int a) { + if (a > 0) + return; + else // comment +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: don't use else after return +// CHECK-FIXES: {{^}} // comment + return; + + if (a > 0) { + return; + } else { // comment +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: don't use else after return +// CHECK-FIXES: } // comment + return; + } + + if (a > 0) { + f(0); + if (a > 10) + return; + } else { + return; + } +} +