[RISCV] Match vcompress during shuffle lowering (#117748)
[llvm-project.git] / clang-tools-extra / clang-tidy / readability / AvoidReturnWithVoidValueCheck.cpp
blobf077040a35295e97c9f4606787757a6a04e0190e
1 //===--- AvoidReturnWithVoidValueCheck.cpp - clang-tidy -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "AvoidReturnWithVoidValueCheck.h"
10 #include "../utils/BracesAroundStatement.h"
11 #include "../utils/LexerUtils.h"
13 using namespace clang::ast_matchers;
15 namespace clang::tidy::readability {
17 static constexpr char IgnoreMacrosName[] = "IgnoreMacros";
18 static const bool IgnoreMacrosDefault = true;
20 static constexpr char StrictModeName[] = "StrictMode";
21 static const bool StrictModeDefault = true;
23 AvoidReturnWithVoidValueCheck::AvoidReturnWithVoidValueCheck(
24 StringRef Name, ClangTidyContext *Context)
25 : ClangTidyCheck(Name, Context),
26 IgnoreMacros(
27 Options.getLocalOrGlobal(IgnoreMacrosName, IgnoreMacrosDefault)),
28 StrictMode(Options.getLocalOrGlobal(StrictModeName, StrictModeDefault)) {}
30 void AvoidReturnWithVoidValueCheck::registerMatchers(MatchFinder *Finder) {
31 Finder->addMatcher(
32 returnStmt(
33 hasReturnValue(allOf(hasType(voidType()), unless(initListExpr()))),
34 optionally(hasParent(
35 compoundStmt(
36 optionally(hasParent(functionDecl().bind("function_parent"))))
37 .bind("compound_parent"))))
38 .bind("void_return"),
39 this);
42 void AvoidReturnWithVoidValueCheck::check(
43 const MatchFinder::MatchResult &Result) {
44 const auto *VoidReturn = Result.Nodes.getNodeAs<ReturnStmt>("void_return");
45 if (IgnoreMacros && VoidReturn->getBeginLoc().isMacroID())
46 return;
47 const auto *SurroundingBlock =
48 Result.Nodes.getNodeAs<CompoundStmt>("compound_parent");
49 if (!StrictMode && !SurroundingBlock)
50 return;
51 DiagnosticBuilder Diag = diag(VoidReturn->getBeginLoc(),
52 "return statement within a void function "
53 "should not have a specified return value");
54 const SourceLocation SemicolonPos = utils::lexer::findNextTerminator(
55 VoidReturn->getEndLoc(), *Result.SourceManager, getLangOpts());
56 if (SemicolonPos.isInvalid())
57 return;
58 if (!SurroundingBlock) {
59 const auto BraceInsertionHints = utils::getBraceInsertionsHints(
60 VoidReturn, getLangOpts(), *Result.SourceManager,
61 VoidReturn->getBeginLoc());
62 if (BraceInsertionHints)
63 Diag << BraceInsertionHints.openingBraceFixIt()
64 << BraceInsertionHints.closingBraceFixIt();
66 Diag << FixItHint::CreateRemoval(VoidReturn->getReturnLoc());
67 const auto *FunctionParent =
68 Result.Nodes.getNodeAs<FunctionDecl>("function_parent");
69 if (!FunctionParent ||
70 (SurroundingBlock && SurroundingBlock->body_back() != VoidReturn))
71 // If this is not the last statement in a function body, we add a `return`.
72 Diag << FixItHint::CreateInsertion(SemicolonPos.getLocWithOffset(1),
73 " return;", true);
76 void AvoidReturnWithVoidValueCheck::storeOptions(
77 ClangTidyOptions::OptionMap &Opts) {
78 Options.store(Opts, IgnoreMacrosName, IgnoreMacros);
79 Options.store(Opts, StrictModeName, StrictMode);
82 } // namespace clang::tidy::readability