-
Notifications
You must be signed in to change notification settings - Fork 12k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[C++20][Coroutines] lambda-coroutine with promise_type ctor. #84519
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-coroutines Author: Andreas Fertig (andreasfertig) ChangesThis is a follow-up of #84064. It turned out that a coroutine-lambda with a Full diff: https://github.com/llvm/llvm-project/pull/84519.diff 3 Files Affected:
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 301a5ff72a3b2a..79da92083a2be7 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -596,8 +596,21 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
// Add implicit object parameter.
if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
- if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
- ExprResult ThisExpr = ActOnCXXThis(Loc);
+ if (MD->isImplicitObjectMemberFunction()) {
+ ExprResult ThisExpr{};
+
+ if (isLambdaCallOperator(MD) && !MD->isStatic()) {
+ Qualifiers ThisQuals = MD->getMethodQualifiers();
+ CXXRecordDecl *Record = MD->getParent();
+
+ Sema::CXXThisScopeRAII ThisScope(*this, Record, ThisQuals,
+ Record != nullptr);
+
+ ThisExpr = ActOnCXXThis(Loc, /*ThisRefersToClosureObject=*/true);
+ } else {
+ ThisExpr = ActOnCXXThis(Loc);
+ }
+
if (ThisExpr.isInvalid())
return nullptr;
ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
diff --git a/clang/test/SemaCXX/coroutine-promise-ctor-lambda.cpp b/clang/test/SemaCXX/coroutine-promise-ctor-lambda.cpp
new file mode 100644
index 00000000000000..92e9a006c3a8d9
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-promise-ctor-lambda.cpp
@@ -0,0 +1,71 @@
+// 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>
+ promise_type(This&,
+ TheRest&&...)
+ {
+ }
+ };
+};
+
+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/cxx23-coroutine-promise-ctor-static-callop-lambda.cpp b/clang/test/SemaCXX/cxx23-coroutine-promise-ctor-static-callop-lambda.cpp
new file mode 100644
index 00000000000000..0e9e63bce86b87
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-coroutine-promise-ctor-static-callop-lambda.cpp
@@ -0,0 +1,47 @@
+// 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 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... TheRest>
+ promise_type(TheRest&&...)
+ {
+ }
+ };
+};
+
+
+int main()
+{
+ auto lamb = []() static -> Generator {
+ co_return;
+ };
+
+ static_assert(sizeof(decltype(lamb)) == 1);
+}
+
|
@ChuanqiXu9 @erichkeane @cor3ntin here is a dedicated patch to support a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick
ff5f858
to
3083833
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a changelog entry for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
This is a follow-up of llvm#84064. It turned out that a coroutine-lambda with a `promise_type` and a user-defined constructor ignores the `this` pointer. Per http://eel.is/c++draft/dcl.fct.def.coroutine#4, in such a case, the first parameter to the constructor is an lvalue of `*this`.
3083833
to
cdeb381
Compare
Done! |
You can test this locally with the following command:git-clang-format --diff c54e0524eeffcf2c5428cd2bc0449a1989e82cd8 7d06524095a48cd6ea5fde089d857cb2b0aa6efb -- clang/test/SemaCXX/coroutine-promise-ctor-lambda.cpp clang/test/SemaCXX/cxx23-coroutine-promise-ctor-static-callop-lambda.cpp clang/lib/Sema/SemaCoroutine.cpp clang/test/SemaCXX/gh84064-1.cpp View the diff from clang-format here.diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index d8359367b9..29e4a33199 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1673,7 +1673,6 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
if (NewExpr.isInvalid())
return false;
-
// Make delete call.
QualType OpDeleteQualType = OperatorDelete->getType();
|
This is a follow-up of #84064. It turned out that a coroutine-lambda with a
promise_type
and a user-defined constructor ignores thethis
pointer. Per http://eel.is/c++draft/dcl.fct.def.coroutine#4, in such a case, the first parameter to the constructor is an lvalue of*this
.