Index: clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tidy/misc/CMakeLists.txt +++ clang-tidy/misc/CMakeLists.txt @@ -3,6 +3,7 @@ add_clang_library(clangTidyMiscModule ArgumentCommentCheck.cpp BoolPointerImplicitConversion.cpp + ElseAfterReturnCheck.cpp MiscTidyModule.cpp SwappedArgumentsCheck.cpp UndelegatedConstructor.cpp Index: clang-tidy/misc/ElseAfterReturnCheck.h =================================================================== --- /dev/null +++ clang-tidy/misc/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_MISC_ELSE_AFTER_RETURN_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_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_MISC_ELSE_AFTER_RETURN_H + Index: clang-tidy/misc/ElseAfterReturnCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/misc/ElseAfterReturnCheck.cpp @@ -0,0 +1,45 @@ +//===--- 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 here"); + 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/misc/MiscTidyModule.cpp =================================================================== --- clang-tidy/misc/MiscTidyModule.cpp +++ clang-tidy/misc/MiscTidyModule.cpp @@ -12,6 +12,7 @@ #include "../ClangTidyModuleRegistry.h" #include "ArgumentCommentCheck.h" #include "BoolPointerImplicitConversion.h" +#include "ElseAfterReturnCheck.h" #include "SwappedArgumentsCheck.h" #include "UndelegatedConstructor.h" #include "UnusedRAII.h" @@ -27,6 +28,8 @@ CheckFactories.registerCheck("misc-argument-comment"); CheckFactories.registerCheck( "misc-bool-pointer-implicit-conversion"); + CheckFactories.registerCheck( + "misc-else-after-return"); CheckFactories.registerCheck( "misc-swapped-arguments"); CheckFactories.registerCheck( Index: test/clang-tidy/misc-else-after-return.cpp =================================================================== --- /dev/null +++ test/clang-tidy/misc-else-after-return.cpp @@ -0,0 +1,28 @@ +// RUN: $(dirname %s)/check_clang_tidy.sh %s misc-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 here +// CHECK-FIXES: {{^}} // comment + return; + + if (a > 0) { + return; + } else { // comment +// CHECK-MESSAGES: warning: don't use else here +// CHECK-FIXES: } // comment + return; + } + + if (a > 0) { + f(0); + if (a > 10) + return; + } else { + return; + } +} +