Skip to content

Commit 011624d

Browse files
committed
Add documentation and simplify test
1 parent f277796 commit 011624d

File tree

3 files changed

+24
-45
lines changed

3 files changed

+24
-45
lines changed

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ Changes in existing checks
265265
<clang-tidy/checks/performance/unnecessary-value-param>` check performance by
266266
tolerating fix-it breaking compilation when functions is used as pointers
267267
to avoid matching usage of functions within the current compilation unit.
268+
Also suppressed this check for coroutine functions because it may not be safe
269+
and suggested fixes may result in hard-to-find bugs and crashes.
268270

269271
- Improved :doc:`readability-convert-member-functions-to-static
270272
<clang-tidy/checks/readability/convert-member-functions-to-static>` check by

clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ the following heuristic is employed:
1818
on it, or it is used as const reference or value argument in constructors or
1919
function calls.
2020

21+
Note: This check does not suggest passing parameters by reference in coroutines
22+
because, after a coroutine suspend point, references could be dangling and no
23+
longer valid, so suggested changes may result in hard-to-find bugs and crashes.
24+
2125
Example:
2226

2327
.. code-block:: c++

clang-tools-extra/test/clang-tidy/checkers/performance/unnecessary-value-param-coroutine.cpp

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,32 @@
22

33
namespace std {
44

5-
template <typename R, typename...> struct coroutine_traits {
6-
using promise_type = typename R::promise_type;
5+
template <class Ret, typename... T> struct coroutine_traits {
6+
using promise_type = typename Ret::promise_type;
77
};
88

9-
template <typename Promise = void> struct coroutine_handle;
10-
11-
template <> struct coroutine_handle<void> {
12-
static coroutine_handle from_address(void *addr) noexcept {
13-
coroutine_handle me;
14-
me.ptr = addr;
15-
return me;
16-
}
17-
void operator()() { resume(); }
18-
void *address() const noexcept { return ptr; }
19-
void resume() const { }
20-
void destroy() const { }
21-
bool done() const { return true; }
22-
coroutine_handle &operator=(decltype(nullptr)) {
23-
ptr = nullptr;
24-
return *this;
25-
}
26-
coroutine_handle(decltype(nullptr)) : ptr(nullptr) {}
27-
coroutine_handle() : ptr(nullptr) {}
28-
// void reset() { ptr = nullptr; } // add to P0057?
29-
explicit operator bool() const { return ptr; }
30-
31-
protected:
32-
void *ptr;
9+
template <class Promise = void> struct coroutine_handle {
10+
static coroutine_handle from_address(void *) noexcept;
11+
static coroutine_handle from_promise(Promise &promise);
12+
constexpr void *address() const noexcept;
3313
};
3414

35-
template <typename Promise> struct coroutine_handle : coroutine_handle<> {
36-
using coroutine_handle<>::operator=;
37-
38-
static coroutine_handle from_address(void *addr) noexcept {
39-
coroutine_handle me;
40-
me.ptr = addr;
41-
return me;
42-
}
43-
44-
Promise &promise() const {
45-
return *reinterpret_cast<Promise *>(
46-
__builtin_coro_promise(ptr, alignof(Promise), false));
47-
}
48-
static coroutine_handle from_promise(Promise &promise) {
49-
coroutine_handle p;
50-
p.ptr = __builtin_coro_promise(&promise, alignof(Promise), true);
51-
return p;
52-
}
15+
template <> struct coroutine_handle<void> {
16+
template <class PromiseType>
17+
coroutine_handle(coroutine_handle<PromiseType>) noexcept;
18+
static coroutine_handle from_address(void *);
19+
constexpr void *address() const noexcept;
5320
};
5421

5522
struct suspend_always {
5623
bool await_ready() noexcept { return false; }
57-
void await_suspend(std::coroutine_handle<>) noexcept {}
24+
void await_suspend(coroutine_handle<>) noexcept {}
25+
void await_resume() noexcept {}
26+
};
27+
28+
struct suspend_never {
29+
bool await_ready() noexcept { return true; }
30+
void await_suspend(coroutine_handle<>) noexcept {}
5831
void await_resume() noexcept {}
5932
};
6033

0 commit comments

Comments
 (0)