1 //===--- ElseAfterReturnCheck.cpp - clang-tidy-----------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "ElseAfterReturnCheck.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 14 using namespace clang::ast_matchers; 15 16 namespace clang { 17 namespace tidy { 18 namespace readability { 19 20 void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) { 21 // FIXME: Support continue, break and throw. 22 Finder->addMatcher( 23 compoundStmt( 24 forEach(ifStmt(hasThen(stmt(anyOf(returnStmt(), 25 compoundStmt(has(returnStmt()))))), 26 hasElse(stmt().bind("else"))) 27 .bind("if"))), 28 this); 29 } 30 31 static FixItHint removeToken(SourceLocation Loc) { 32 return FixItHint::CreateRemoval(CharSourceRange::getTokenRange(Loc, Loc)); 33 } 34 35 void ElseAfterReturnCheck::check(const MatchFinder::MatchResult &Result) { 36 const auto *If = Result.Nodes.getNodeAs<IfStmt>("if"); 37 SourceLocation ElseLoc = If->getElseLoc(); 38 DiagnosticBuilder Diag = diag(ElseLoc, "don't use else after return"); 39 Diag << removeToken(ElseLoc); 40 41 // FIXME: Removing the braces isn't always safe. Do a more careful analysis. 42 // FIXME: Change clang-format to correctly un-indent the code. 43 if (const auto *CS = Result.Nodes.getNodeAs<CompoundStmt>("else")) 44 Diag << removeToken(CS->getLBracLoc()) << removeToken(CS->getRBracLoc()); 45 } 46 47 } // namespace readability 48 } // namespace tidy 49 } // namespace clang 50