clang-tools 22.0.0git
AvoidReturnWithVoidValueCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
11#include "../utils/LexerUtils.h"
12
13using namespace clang::ast_matchers;
14
16
17static constexpr char IgnoreMacrosName[] = "IgnoreMacros";
18static const bool IgnoreMacrosDefault = true;
19
20static constexpr char StrictModeName[] = "StrictMode";
21static const bool StrictModeDefault = true;
22
24 StringRef Name, ClangTidyContext *Context)
25 : ClangTidyCheck(Name, Context),
26 IgnoreMacros(Options.get(IgnoreMacrosName, IgnoreMacrosDefault)),
27 StrictMode(Options.get(StrictModeName, StrictModeDefault)) {}
28
30 Finder->addMatcher(
31 returnStmt(
32 hasReturnValue(allOf(hasType(voidType()), unless(initListExpr()))),
33 optionally(hasParent(
34 compoundStmt(
35 optionally(hasParent(functionDecl().bind("function_parent"))))
36 .bind("compound_parent"))))
37 .bind("void_return"),
38 this);
39}
40
42 const MatchFinder::MatchResult &Result) {
43 const auto *VoidReturn = Result.Nodes.getNodeAs<ReturnStmt>("void_return");
44 if (IgnoreMacros && VoidReturn->getBeginLoc().isMacroID())
45 return;
46 const auto *SurroundingBlock =
47 Result.Nodes.getNodeAs<CompoundStmt>("compound_parent");
48 if (!StrictMode && !SurroundingBlock)
49 return;
50 DiagnosticBuilder Diag = diag(VoidReturn->getBeginLoc(),
51 "return statement within a void function "
52 "should not have a specified return value");
53 const SourceLocation SemicolonPos = utils::lexer::findNextTerminator(
54 VoidReturn->getEndLoc(), *Result.SourceManager, getLangOpts());
55 if (SemicolonPos.isInvalid())
56 return;
57 if (!SurroundingBlock) {
58 const auto BraceInsertionHints = utils::getBraceInsertionsHints(
59 VoidReturn, getLangOpts(), *Result.SourceManager,
60 VoidReturn->getBeginLoc());
61 if (BraceInsertionHints)
62 Diag << BraceInsertionHints.openingBraceFixIt()
63 << BraceInsertionHints.closingBraceFixIt();
64 }
65 Diag << FixItHint::CreateRemoval(VoidReturn->getReturnLoc());
66 const auto *FunctionParent =
67 Result.Nodes.getNodeAs<FunctionDecl>("function_parent");
68 if (!FunctionParent ||
69 (SurroundingBlock && SurroundingBlock->body_back() != VoidReturn))
70 // If this is not the last statement in a function body, we add a `return`.
71 Diag << FixItHint::CreateInsertion(SemicolonPos.getLocWithOffset(1),
72 " return;", true);
73}
74
75void AvoidReturnWithVoidValueCheck::storeOptions(
77 Options.store(Opts, IgnoreMacrosName, IgnoreMacros);
78 Options.store(Opts, StrictModeName, StrictMode);
79}
80
81} // namespace clang::tidy::readability
This file provides utilities to put braces around a statement.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
AvoidReturnWithVoidValueCheck(StringRef Name, ClangTidyContext *Context)
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
BraceInsertionHints getBraceInsertionsHints(const Stmt *const S, const LangOptions &LangOpts, const SourceManager &SM, SourceLocation StartLoc, SourceLocation EndLocHint)
Create fix-it hints for braces that wrap the given statement when applied.
llvm::StringMap< ClangTidyValue > OptionMap