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//===----------------------------------------------------------------------===//
8
9#include "AvoidReturnWithVoidValueCheck.h"
10#include "../utils/BracesAroundStatement.h"
11#include "../utils/LexerUtils.h"
12
13using namespace clang::ast_matchers;
14
15namespace clang::tidy::readability {
16
17static constexpr char IgnoreMacrosName[] = "IgnoreMacros";
18static const bool IgnoreMacrosDefault = true;
19
20static constexpr char StrictModeName[] = "StrictMode";
21static const bool StrictModeDefault = true;
22
23AvoidReturnWithVoidValueCheck::AvoidReturnWithVoidValueCheck(
24 StringRef Name, ClangTidyContext *Context)
25 : ClangTidyCheck(Name, Context),
26 IgnoreMacros(
27 Options.getLocalOrGlobal(LocalName: IgnoreMacrosName, Default: IgnoreMacrosDefault)),
28 StrictMode(Options.getLocalOrGlobal(LocalName: StrictModeName, Default: StrictModeDefault)) {}
29
30void AvoidReturnWithVoidValueCheck::registerMatchers(MatchFinder *Finder) {
31 Finder->addMatcher(
32 NodeMatch: returnStmt(
33 hasReturnValue(InnerMatcher: allOf(hasType(InnerMatcher: voidType()), unless(initListExpr()))),
34 optionally(hasParent(
35 compoundStmt(
36 optionally(hasParent(functionDecl().bind(ID: "function_parent"))))
37 .bind(ID: "compound_parent"))))
38 .bind(ID: "void_return"),
39 Action: this);
40}
41
42void AvoidReturnWithVoidValueCheck::check(
43 const MatchFinder::MatchResult &Result) {
44 const auto *VoidReturn = Result.Nodes.getNodeAs<ReturnStmt>(ID: "void_return");
45 if (IgnoreMacros && VoidReturn->getBeginLoc().isMacroID())
46 return;
47 const auto *SurroundingBlock =
48 Result.Nodes.getNodeAs<CompoundStmt>(ID: "compound_parent");
49 if (!StrictMode && !SurroundingBlock)
50 return;
51 DiagnosticBuilder Diag = diag(Loc: VoidReturn->getBeginLoc(),
52 Description: "return statement within a void function "
53 "should not have a specified return value");
54 const SourceLocation SemicolonPos = utils::lexer::findNextTerminator(
55 Start: VoidReturn->getEndLoc(), SM: *Result.SourceManager, LangOpts: 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();
65 }
66 Diag << FixItHint::CreateRemoval(RemoveRange: VoidReturn->getReturnLoc());
67 const auto *FunctionParent =
68 Result.Nodes.getNodeAs<FunctionDecl>(ID: "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(InsertionLoc: SemicolonPos.getLocWithOffset(Offset: 1),
73 Code: " return;", BeforePreviousInsertions: true);
74}
75
76void AvoidReturnWithVoidValueCheck::storeOptions(
77 ClangTidyOptions::OptionMap &Opts) {
78 Options.store(Options&: Opts, LocalName: IgnoreMacrosName, Value: IgnoreMacros);
79 Options.store(Options&: Opts, LocalName: StrictModeName, Value: StrictMode);
80}
81
82} // namespace clang::tidy::readability
83

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang-tools-extra/clang-tidy/readability/AvoidReturnWithVoidValueCheck.cpp