diff options
author | Andreas Fertig <andy@cppinsights.io> | 2024-03-08 17:10:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-08 08:10:20 -0800 |
commit | 35d3b33ba5c9b90443ac985f2521b78f84b611fe (patch) | |
tree | 036b648437721673350f9a71db4d10d4fcadd1bb /clang/test | |
parent | 0456a32a2a622a73e01b01c65c21973ac5a689fc (diff) | |
download | llvm-35d3b33ba5c9b90443ac985f2521b78f84b611fe.zip llvm-35d3b33ba5c9b90443ac985f2521b78f84b611fe.tar.gz llvm-35d3b33ba5c9b90443ac985f2521b78f84b611fe.tar.bz2 |
[C++20][Coroutines] Lambda-coroutine with operator new in promise_type (#84193)
Fix #84064
According to http://eel.is/c++draft/dcl.fct.def.coroutine#9 the first
parameter for overload resolution of `operator new` is `size_t` followed
by the arguments of the coroutine function.
http://eel.is/c++draft/dcl.fct.def.coroutine#4 states that the first
argument is the lvalue of `*this` if the coroutine is a member function.
Before this patch, Clang handled class types correctly but ignored
lambdas. This patch adds support for lambda coroutines with a
`promise_type` that implements a custom `operator new`.
The patch does consider C++23 `static operator()`, which already worked
as there is no `this` parameter.
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/SemaCXX/gh84064-1.cpp | 79 | ||||
-rw-r--r-- | clang/test/SemaCXX/gh84064-2.cpp | 53 |
2 files changed, 132 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/gh84064-1.cpp b/clang/test/SemaCXX/gh84064-1.cpp new file mode 100644 index 0000000..d9c2738 --- /dev/null +++ b/clang/test/SemaCXX/gh84064-1.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -I%S/Inputs -std=c++20 %s + +// expected-no-diagnostics + +#include "std-coroutine.h" + +using size_t = decltype(sizeof(0)); + +struct Generator { + struct promise_type { + int _val{}; + + Generator get_return_object() noexcept + { + return {}; + } + + std::suspend_never initial_suspend() noexcept + { + return {}; + } + + std::suspend_always final_suspend() noexcept + { + return {}; + } + + void return_void() noexcept {} + void unhandled_exception() noexcept {} + + template<typename This, typename... TheRest> + static void* + operator new(size_t size, + This&, + TheRest&&...) noexcept + { + return nullptr; + } + + static void operator delete(void*, size_t) + { + } + }; +}; + +struct CapturingThisTest +{ + int x{}; + + void AsPointer() + { + auto lamb = [=,this]() -> Generator { + int y = x; + co_return; + }; + + static_assert(sizeof(decltype(lamb)) == sizeof(void*)); + } + + void AsStarThis() + { + auto lamb = [*this]() -> Generator { + int y = x; + co_return; + }; + + static_assert(sizeof(decltype(lamb)) == sizeof(int)); + } +}; + +int main() +{ + auto lamb = []() -> Generator { + co_return; + }; + + static_assert(sizeof(decltype(lamb)) == 1); +} + diff --git a/clang/test/SemaCXX/gh84064-2.cpp b/clang/test/SemaCXX/gh84064-2.cpp new file mode 100644 index 0000000..457de43 --- /dev/null +++ b/clang/test/SemaCXX/gh84064-2.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -I%S/Inputs -std=c++23 %s + +// expected-no-diagnostics + +#include "std-coroutine.h" + +using size_t = decltype(sizeof(0)); + +struct GeneratorStatic { + struct promise_type { + int _val{}; + + GeneratorStatic get_return_object() noexcept + { + return {}; + } + + std::suspend_never initial_suspend() noexcept + { + return {}; + } + + std::suspend_always final_suspend() noexcept + { + return {}; + } + + void return_void() noexcept {} + void unhandled_exception() noexcept {} + + template<typename... TheRest> + static void* + operator new(size_t size, + TheRest&&...) noexcept + { + return nullptr; + } + + static void operator delete(void*, size_t) + { + } + }; +}; + + +int main() +{ + auto lambCpp23 = []() static -> GeneratorStatic { + co_return; + }; + + static_assert(sizeof(decltype(lambCpp23)) == 1); +} |