Skip to content

Commit 05491e0

Browse files
authored
[clang-tidy] add 'IgnoreMarcos' option to 'avoid-goto' check (#143554)
1 parent 117e51d commit 05491e0

File tree

5 files changed

+81
-12
lines changed

5 files changed

+81
-12
lines changed

clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,20 @@ namespace {
1717
AST_MATCHER(GotoStmt, isForwardJumping) {
1818
return Node.getBeginLoc() < Node.getLabel()->getBeginLoc();
1919
}
20+
21+
AST_MATCHER(GotoStmt, isInMacro) {
22+
return Node.getBeginLoc().isMacroID() && Node.getEndLoc().isMacroID();
23+
}
2024
} // namespace
2125

26+
AvoidGotoCheck::AvoidGotoCheck(StringRef Name, ClangTidyContext *Context)
27+
: ClangTidyCheck(Name, Context),
28+
IgnoreMacros(Options.get("IgnoreMacros", false)) {}
29+
30+
void AvoidGotoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
31+
Options.store(Opts, "IgnoreMacros", IgnoreMacros);
32+
}
33+
2234
void AvoidGotoCheck::registerMatchers(MatchFinder *Finder) {
2335
// TODO: This check does not recognize `IndirectGotoStmt` which is a
2436
// GNU extension. These must be matched separately and an AST matcher
@@ -29,7 +41,10 @@ void AvoidGotoCheck::registerMatchers(MatchFinder *Finder) {
2941
auto Loop = mapAnyOf(forStmt, cxxForRangeStmt, whileStmt, doStmt);
3042
auto NestedLoop = Loop.with(hasAncestor(Loop));
3143

32-
Finder->addMatcher(gotoStmt(anyOf(unless(hasAncestor(NestedLoop)),
44+
const ast_matchers::internal::Matcher<GotoStmt> Anything = anything();
45+
46+
Finder->addMatcher(gotoStmt(IgnoreMacros ? unless(isInMacro()) : Anything,
47+
anyOf(unless(hasAncestor(NestedLoop)),
3348
unless(isForwardJumping())))
3449
.bind("goto"),
3550
this);

clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@ namespace clang::tidy::cppcoreguidelines {
2020
/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-goto.html
2121
class AvoidGotoCheck : public ClangTidyCheck {
2222
public:
23-
AvoidGotoCheck(StringRef Name, ClangTidyContext *Context)
24-
: ClangTidyCheck(Name, Context) {}
23+
AvoidGotoCheck(StringRef Name, ClangTidyContext *Context);
2524
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
2625
return LangOpts.CPlusPlus;
2726
}
27+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
2828
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
2929
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
30+
31+
private:
32+
const bool IgnoreMacros;
3033
};
3134

3235
} // namespace clang::tidy::cppcoreguidelines

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,19 @@ Changes in existing checks
203203
<clang-tidy/checks/concurrency/mt-unsafe>` check by fixing a false positive
204204
where ``strerror`` was flagged as MT-unsafe.
205205

206+
- Improved :doc:`cppcoreguidelines-avoid-goto
207+
<clang-tidy/checks/cppcoreguidelines/avoid-goto>` check by adding the option
208+
`IgnoreMacros` to ignore ``goto`` labels defined in macros.
209+
206210
- Improved :doc:`google-readability-namespace-comments
207211
<clang-tidy/checks/google/readability-namespace-comments>` check by adding
208212
the option `AllowOmittingNamespaceComments` to accept if a namespace comment
209213
is omitted entirely.
210214

215+
- Improved :doc:`hicpp-avoid-goto
216+
<clang-tidy/checks/hicpp/avoid-goto>` check by adding the option
217+
`IgnoreMacros` to ignore ``goto`` labels defined in macros.
218+
211219
- Improved :doc:`llvm-namespace-comment
212220
<clang-tidy/checks/llvm/namespace-comment>` check by adding the option
213221
`AllowOmittingNamespaceComments` to accept if a namespace comment is omitted

clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-goto.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,12 @@ Modern C++ needs ``goto`` only to jump out of nested loops.
5050
some_operation();
5151

5252
All other uses of ``goto`` are diagnosed in `C++`.
53+
54+
55+
Options
56+
-------
57+
58+
.. option:: IgnoreMacros
59+
60+
If set to `true`, the check will not warn if a ``goto`` statement is
61+
expanded from a macro. Default is `false`.

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-goto.cpp

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
1-
// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-goto %t
1+
// RUN: %check_clang_tidy -check-suffix=,MACRO %s cppcoreguidelines-avoid-goto %t
2+
// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-goto %t -- -config="{CheckOptions: { cppcoreguidelines-avoid-goto.IgnoreMacros: true }}"
23

34
void noop() {}
45

56
int main() {
67
noop();
78
goto jump_to_me;
8-
// CHECK-NOTES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
9-
// CHECK-NOTES: [[@LINE+3]]:1: note: label defined here
9+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
10+
// CHECK-MESSAGES: [[@LINE+3]]:1: note: label defined here
1011
noop();
1112

1213
jump_to_me:;
1314

1415
jump_backwards:;
1516
noop();
1617
goto jump_backwards;
17-
// CHECK-NOTES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
18-
// CHECK-NOTES: [[@LINE-4]]:1: note: label defined here
18+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
19+
// CHECK-MESSAGES: [[@LINE-4]]:1: note: label defined here
1920

2021
goto jump_in_line;
2122
;
2223
jump_in_line:;
23-
// CHECK-NOTES: [[@LINE-3]]:3: warning: avoid using 'goto' for flow control
24-
// CHECK-NOTES: [[@LINE-2]]:1: note: label defined here
24+
// CHECK-MESSAGES: [[@LINE-3]]:3: warning: avoid using 'goto' for flow control
25+
// CHECK-MESSAGES: [[@LINE-2]]:1: note: label defined here
2526

2627
// Test the GNU extension https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
2728
some_label:;
@@ -132,8 +133,41 @@ void jump_out_backwards() {
132133
for (int j = 0; j < 10; ++j) {
133134
if (i * j > 80)
134135
goto before_the_loop;
135-
// CHECK-NOTES: [[@LINE-1]]:9: warning: avoid using 'goto' for flow control
136-
// CHECK-NOTES: [[@LINE-8]]:1: note: label defined here
136+
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: avoid using 'goto' for flow control
137+
// CHECK-MESSAGES: [[@LINE-8]]:1: note: label defined here
137138
}
138139
}
139140
}
141+
142+
#define macro_goto_code \
143+
noop(); \
144+
goto jump_to_me; \
145+
noop(); \
146+
jump_to_me:; \
147+
148+
#define macro_goto_label jump_to_me:;
149+
#define macro_goto_jump goto jump_to_me;
150+
151+
void inside_macro_all() {
152+
macro_goto_code
153+
// CHECK-MESSAGES-MACRO: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
154+
// CHECK-MESSAGES-MACRO: [[@LINE-2]]:3: note: label defined here
155+
}
156+
157+
void inside_macro_label() {
158+
noop();
159+
goto jump_to_me;
160+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
161+
// CHECK-MESSAGES: [[@LINE+2]]:3: note: label defined here
162+
noop();
163+
macro_goto_label
164+
}
165+
166+
void inside_macro_goto() {
167+
noop();
168+
macro_goto_jump
169+
// CHECK-MESSAGES-MACRO: [[@LINE-1]]:3: warning: avoid using 'goto' for flow control
170+
// CHECK-MESSAGES-MACRO: [[@LINE+2]]:3: note: label defined here
171+
noop();
172+
jump_to_me:;
173+
}

0 commit comments

Comments
 (0)