Skip to content

Commit 71a7da3

Browse files
committed
[clang-tidy] Add fix-its to avoid-return-with-void-value check
1 parent 5bd374d commit 71a7da3

File tree

3 files changed

+49
-10
lines changed

3 files changed

+49
-10
lines changed

clang-tools-extra/clang-tidy/readability/AvoidReturnWithVoidValueCheck.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@
1010
#include "clang/AST/Stmt.h"
1111
#include "clang/ASTMatchers/ASTMatchFinder.h"
1212
#include "clang/ASTMatchers/ASTMatchers.h"
13+
#include "clang/Basic/Diagnostic.h"
14+
#include "clang/Lex/Lexer.h"
1315

1416
using namespace clang::ast_matchers;
1517

1618
namespace clang::tidy::readability {
1719

18-
static constexpr auto IgnoreMacrosName = "IgnoreMacros";
19-
static constexpr auto IgnoreMacrosDefault = true;
20+
static constexpr char IgnoreMacrosName[] = "IgnoreMacros";
21+
static const bool IgnoreMacrosDefault = true;
2022

21-
static constexpr auto StrictModeName = "StrictMode";
22-
static constexpr auto StrictModeDefault = true;
23+
static constexpr char StrictModeName[] = "StrictMode";
24+
static const bool StrictModeDefault = true;
2325

2426
AvoidReturnWithVoidValueCheck::AvoidReturnWithVoidValueCheck(
2527
StringRef Name, ClangTidyContext *Context)
@@ -40,12 +42,35 @@ void AvoidReturnWithVoidValueCheck::registerMatchers(MatchFinder *Finder) {
4042
void AvoidReturnWithVoidValueCheck::check(
4143
const MatchFinder::MatchResult &Result) {
4244
const auto *VoidReturn = Result.Nodes.getNodeAs<ReturnStmt>("void_return");
43-
if (IgnoreMacros && VoidReturn->getBeginLoc().isMacroID())
45+
if (IgnoreMacros && VoidReturn->getBeginLoc().isMacroID()) {
4446
return;
45-
if (!StrictMode && !Result.Nodes.getNodeAs<CompoundStmt>("compound_parent"))
47+
}
48+
const auto *SurroundingBlock =
49+
Result.Nodes.getNodeAs<CompoundStmt>("compound_parent");
50+
if (!StrictMode && !SurroundingBlock) {
4651
return;
47-
diag(VoidReturn->getBeginLoc(), "return statement within a void function "
48-
"should not have a specified return value");
52+
}
53+
DiagnosticBuilder Diag = diag(VoidReturn->getBeginLoc(),
54+
"return statement within a void function "
55+
"should not have a specified return value");
56+
std::optional<Token> SemicolonPos =
57+
Lexer::findNextToken(VoidReturn->getRetValue()->getEndLoc(),
58+
*Result.SourceManager, getLangOpts());
59+
if (!SemicolonPos) {
60+
return;
61+
}
62+
const StringRef ReturnExpr =
63+
Lexer::getSourceText(CharSourceRange::getTokenRange(
64+
VoidReturn->getRetValue()->getSourceRange()),
65+
*Result.SourceManager, getLangOpts());
66+
std::string Replacement = (ReturnExpr + "; return;").str();
67+
if (!SurroundingBlock) {
68+
Replacement = "{" + Replacement + "}";
69+
}
70+
Diag << FixItHint::CreateReplacement(
71+
CharSourceRange::getTokenRange(VoidReturn->getBeginLoc(),
72+
SemicolonPos->getEndLoc()),
73+
Replacement);
4974
}
5075

5176
void AvoidReturnWithVoidValueCheck::storeOptions(

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ Changes in existing checks
179179
<clang-tidy/checks/modernize/use-override>` check to also remove any trailing
180180
whitespace when deleting the ``virtual`` keyword.
181181

182+
- Improved :doc:`readability-avoid-return-with-void-value
183+
<clang-tidy/checks/readability/avoid-return-with-void-value>` check by adding
184+
fix-its.
185+
182186
- Improved :doc:`readability-implicit-bool-conversion
183187
<clang-tidy/checks/readability/implicit-bool-conversion>` check to provide
184188
valid fix suggestions for ``static_cast`` without a preceding space and

clang-tools-extra/test/clang-tidy/checkers/readability/avoid-return-with-void-value.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@ void f2() {
1212
return f1();
1313
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
1414
// CHECK-MESSAGES-LENIENT: :[[@LINE-2]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
15+
// CHECK-FIXES: f1(); return;
1516
}
1617

1718
void f3(bool b) {
1819
if (b) return f1();
1920
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
21+
// CHECK-FIXES: if (b) {f1(); return;}
2022
return f2();
2123
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
2224
// CHECK-MESSAGES-LENIENT: :[[@LINE-2]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
25+
// CHECK-FIXES: f2(); return;
26+
// CHECK-FIXES-LENIENT: f2(); return;
2327
}
2428

2529
template<class T>
@@ -29,6 +33,8 @@ void f5() {
2933
return f4<void>();
3034
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
3135
// CHECK-MESSAGES-LENIENT: :[[@LINE-2]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
36+
// CHECK-FIXES: f4<void>(); return;
37+
// CHECK-FIXES-LENIENT: f4<void>(); return;
3238
}
3339

3440
void f6() { return; }
@@ -41,6 +47,8 @@ void f9() {
4147
return (void)f7();
4248
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
4349
// CHECK-MESSAGES-LENIENT: :[[@LINE-2]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
50+
// CHECK-FIXES: (void)f7(); return;
51+
// CHECK-FIXES-LENIENT: (void)f7(); return;
4452
}
4553

4654
#define RETURN_VOID return (void)1
@@ -50,12 +58,12 @@ void f10() {
5058
// CHECK-MESSAGES-INCLUDE-MACROS: :[[@LINE-1]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
5159
}
5260

53-
template <typename A>
61+
template <typename A>
5462
struct C {
5563
C(A) {}
5664
};
5765

58-
template <class T>
66+
template <class T>
5967
C<T> f11() { return {}; }
6068

6169
using VOID = void;
@@ -66,4 +74,6 @@ VOID f13() {
6674
return f12();
6775
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
6876
// CHECK-MESSAGES-LENIENT: :[[@LINE-2]]:5: warning: return statement within a void function should not have a specified return value [readability-avoid-return-with-void-value]
77+
// CHECK-FIXES: f12(); return;
78+
// CHECK-FIXES-LENIENT: f12(); return;
6979
}

0 commit comments

Comments
 (0)