Mercurial > hg > CbC > CbC_llvm
view clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp @ 266:00f31e85ec16 default tip
Added tag current for changeset 31d058e83c98
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 14 Oct 2023 10:13:55 +0900 |
parents | 1f2b6ac9f198 |
children |
line wrap: on
line source
//===--- RedundantControlFlowCheck.cpp - clang-tidy------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "RedundantControlFlowCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Lex/Lexer.h" using namespace clang::ast_matchers; namespace clang::tidy::readability { namespace { const char *const RedundantReturnDiag = "redundant return statement at the end " "of a function with a void return type"; const char *const RedundantContinueDiag = "redundant continue statement at the " "end of loop statement"; bool isLocationInMacroExpansion(const SourceManager &SM, SourceLocation Loc) { return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc); } } // namespace void RedundantControlFlowCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( functionDecl(isDefinition(), returns(voidType()), hasBody(compoundStmt(hasAnySubstatement( returnStmt(unless(has(expr()))))) .bind("return"))), this); Finder->addMatcher( mapAnyOf(forStmt, cxxForRangeStmt, whileStmt, doStmt) .with(hasBody(compoundStmt(hasAnySubstatement(continueStmt())) .bind("continue"))), this); } void RedundantControlFlowCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *Return = Result.Nodes.getNodeAs<CompoundStmt>("return")) checkRedundantReturn(Result, Return); else if (const auto *Continue = Result.Nodes.getNodeAs<CompoundStmt>("continue")) checkRedundantContinue(Result, Continue); } void RedundantControlFlowCheck::checkRedundantReturn( const MatchFinder::MatchResult &Result, const CompoundStmt *Block) { CompoundStmt::const_reverse_body_iterator Last = Block->body_rbegin(); if (const auto *Return = dyn_cast<ReturnStmt>(*Last)) issueDiagnostic(Result, Block, Return->getSourceRange(), RedundantReturnDiag); } void RedundantControlFlowCheck::checkRedundantContinue( const MatchFinder::MatchResult &Result, const CompoundStmt *Block) { CompoundStmt::const_reverse_body_iterator Last = Block->body_rbegin(); if (const auto *Continue = dyn_cast<ContinueStmt>(*Last)) issueDiagnostic(Result, Block, Continue->getSourceRange(), RedundantContinueDiag); } void RedundantControlFlowCheck::issueDiagnostic( const MatchFinder::MatchResult &Result, const CompoundStmt *const Block, const SourceRange &StmtRange, const char *const Diag) { SourceManager &SM = *Result.SourceManager; if (isLocationInMacroExpansion(SM, StmtRange.getBegin())) return; CompoundStmt::const_reverse_body_iterator Previous = ++Block->body_rbegin(); SourceLocation Start; if (Previous != Block->body_rend()) Start = Lexer::findLocationAfterToken( cast<Stmt>(*Previous)->getEndLoc(), tok::semi, SM, getLangOpts(), /*SkipTrailingWhitespaceAndNewLine=*/true); if (!Start.isValid()) Start = StmtRange.getBegin(); auto RemovedRange = CharSourceRange::getCharRange( Start, Lexer::findLocationAfterToken( StmtRange.getEnd(), tok::semi, SM, getLangOpts(), /*SkipTrailingWhitespaceAndNewLine=*/true)); diag(StmtRange.getBegin(), Diag) << FixItHint::CreateRemoval(RemovedRange); } } // namespace clang::tidy::readability