Skip to content

Commit 18d4da2

Browse files
Add the ability to exempt callees from the misc-coroutine-hostile-raii clang-tidy check (#167778)
1 parent a01a921 commit 18d4da2

File tree

5 files changed

+44
-3
lines changed

5 files changed

+44
-3
lines changed

clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,19 @@ CoroutineHostileRAIICheck::CoroutineHostileRAIICheck(StringRef Name,
7373
RAIITypesList(utils::options::parseStringList(
7474
Options.get("RAIITypesList", "std::lock_guard;std::scoped_lock"))),
7575
AllowedAwaitablesList(utils::options::parseStringList(
76-
Options.get("AllowedAwaitablesList", ""))) {}
76+
Options.get("AllowedAwaitablesList", ""))),
77+
AllowedCallees(
78+
utils::options::parseStringList(Options.get("AllowedCallees", ""))) {}
7779

7880
void CoroutineHostileRAIICheck::registerMatchers(MatchFinder *Finder) {
7981
// A suspension happens with co_await or co_yield.
8082
auto ScopedLockable = varDecl(hasType(hasCanonicalType(hasDeclaration(
8183
hasAttr(attr::Kind::ScopedLockable)))))
8284
.bind("scoped-lockable");
8385
auto OtherRAII = varDecl(typeWithNameIn(RAIITypesList)).bind("raii");
84-
auto AllowedSuspend = awaitable(typeWithNameIn(AllowedAwaitablesList));
86+
auto AllowedSuspend = awaitable(
87+
anyOf(typeWithNameIn(AllowedAwaitablesList),
88+
callExpr(callee(functionDecl(hasAnyName(AllowedCallees))))));
8589
Finder->addMatcher(
8690
expr(anyOf(coawaitExpr(unless(AllowedSuspend)), coyieldExpr()),
8791
forEachPrevStmt(
@@ -111,5 +115,7 @@ void CoroutineHostileRAIICheck::storeOptions(
111115
utils::options::serializeStringList(RAIITypesList));
112116
Options.store(Opts, "SafeAwaitableList",
113117
utils::options::serializeStringList(AllowedAwaitablesList));
118+
Options.store(Opts, "SafeCallees",
119+
utils::options::serializeStringList(AllowedCallees));
114120
}
115121
} // namespace clang::tidy::misc

clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class CoroutineHostileRAIICheck : public ClangTidyCheck {
4646
// List of fully qualified awaitable types which are considered safe to
4747
// co_await.
4848
std::vector<StringRef> AllowedAwaitablesList;
49+
// List of callees whose return values are considered safe to directly
50+
// co_await.
51+
std::vector<StringRef> AllowedCallees;
4952
};
5053

5154
} // namespace clang::tidy::misc

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ Changes in existing checks
423423
positives on return of non-const pointer and fix false positives on
424424
pointer-to-member operator.
425425

426+
- Improved :doc:`misc-coroutine-hostile-raii
427+
<clang-tidy/checks/misc/coroutine-hostile-raii>` check by adding the option
428+
`AllowedCallees`, that allows exempting safely awaitable callees from the
429+
check.
430+
426431
- Improved :doc:`misc-header-include-cycle
427432
<clang-tidy/checks/misc/header-include-cycle>` check performance.
428433

clang-tools-extra/docs/clang-tidy/checks/misc/coroutine-hostile-raii.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,23 @@ Options
8181
Eg: `my::safe::awaitable;other::awaitable`
8282
Default is an empty string.
8383

84+
.. option:: AllowedCallees
85+
86+
A semicolon-separated list of callee function names which can
87+
be safely awaited while having hostile RAII objects in scope.
88+
Example usage:
89+
90+
.. code-block:: c++
91+
92+
// Consider option AllowedCallees = "noop"
93+
task noop() { co_return; }
94+
95+
task coro() {
96+
// This persists across the co_await but is not flagged
97+
// because the awaitable is considered safe to await on.
98+
const std::lock_guard l(&mu_);
99+
co_await noop();
100+
}
101+
102+
Eg: `my::safe::await;other::await`
103+
Default is an empty string.

clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// RUN: %check_clang_tidy -std=c++20 %s misc-coroutine-hostile-raii %t \
22
// RUN: -config="{CheckOptions: {\
33
// RUN: misc-coroutine-hostile-raii.RAIITypesList: 'my::Mutex; ::my::other::Mutex', \
4-
// RUN: misc-coroutine-hostile-raii.AllowedAwaitablesList: 'safe::awaitable; ::transformable::awaitable' \
4+
// RUN: misc-coroutine-hostile-raii.AllowedAwaitablesList: 'safe::awaitable; ::transformable::awaitable', \
5+
// RUN: misc-coroutine-hostile-raii.AllowedCallees: 'safe::AwaitFunc; ::safe::Obj::AwaitMethod' \
56
// RUN: }}"
67

78
namespace std {
@@ -145,12 +146,18 @@ namespace safe {
145146
void await_suspend(std::coroutine_handle<>) noexcept {}
146147
void await_resume() noexcept {}
147148
};
149+
std::suspend_always AwaitFunc();
150+
struct Obj {
151+
std::suspend_always AwaitMethod();
152+
};
148153
} // namespace safe
149154
ReturnObject RAIISafeSuspendTest() {
150155
absl::Mutex a;
151156
co_await safe::awaitable{};
152157
using other = safe::awaitable;
153158
co_await other{};
159+
co_await safe::AwaitFunc();
160+
co_await safe::Obj().AwaitMethod();
154161
}
155162

156163
// ================================================================================

0 commit comments

Comments
 (0)