[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Chuanqi Xu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG097208dbf077: [C++20] [Coroutines] Allow promise_type to not 
define return_void or… (authored by ChuanqiXu).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116204/new/

https://reviews.llvm.org/D116204

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaCoroutine.cpp
  clang/test/SemaCXX/coroutines-exp-namespace.cpp
  clang/test/SemaCXX/coroutines.cpp

Index: clang/test/SemaCXX/coroutines.cpp
===
--- clang/test/SemaCXX/coroutines.cpp
+++ clang/test/SemaCXX/coroutines.cpp
@@ -970,19 +970,36 @@
   co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
 }
 
-struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
-  coro get_return_object();
+struct promise_no_return_func {
+  coro get_return_object();
   suspend_always initial_suspend();
   suspend_always final_suspend() noexcept;
   void unhandled_exception();
 };
-// FIXME: The PDTS currently specifies this as UB, technically forbidding a
-// diagnostic.
-coro no_return_value_or_return_void() {
-  // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
+// [dcl.fct.def.coroutine]/p6
+// If searches for the names return_­void and return_­value in the scope of
+// the promise type each find any declarations, the program is ill-formed.
+// [Note 1: If return_­void is found, flowing off the end of a coroutine is
+// equivalent to a co_­return with no operand. Otherwise, flowing off the end
+// of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
+// end note]
+//
+// So it isn't ill-formed if the promise doesn't define return_value and return_void.
+// It is just a potential UB.
+coro no_return_value_or_return_void() {
   co_await a;
 }
 
+// The following two tests that it would emit correct diagnostic message
+// if we co_return in `promise_no_return_func`.
+coro no_return_value_or_return_void_2() {
+  co_return; // expected-error {{no member named 'return_void'}}
+}
+
+coro no_return_value_or_return_void_3() {
+  co_return 43; // expected-error {{no member named 'return_value'}}
+}
+
 struct bad_await_suspend_return {
   bool await_ready();
   // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Index: clang/test/SemaCXX/coroutines-exp-namespace.cpp
===
--- clang/test/SemaCXX/coroutines-exp-namespace.cpp
+++ clang/test/SemaCXX/coroutines-exp-namespace.cpp
@@ -978,19 +978,6 @@
   co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
 }
 
-struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
-  coro get_return_object();
-  suspend_always initial_suspend();
-  suspend_always final_suspend() noexcept;
-  void unhandled_exception();
-};
-// FIXME: The PDTS currently specifies this as UB, technically forbidding a
-// diagnostic.
-coro no_return_value_or_return_void() {
-  // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
-  co_await a;
-}
-
 struct bad_await_suspend_return {
   bool await_ready();
   // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Index: clang/lib/Sema/SemaCoroutine.cpp
===
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -1432,9 +1432,13 @@
   assert(!IsPromiseDependentType &&
  "cannot make statement while the promise type is dependent");
 
-  // [dcl.fct.def.coroutine]/4
-  // The unqualified-ids 'return_void' and 'return_value' are looked up in
-  // the scope of class P. If both are found, the program is ill-formed.
+  // [dcl.fct.def.coroutine]/p6
+  // If searches for the names return_­void and return_­value in the scope of
+  // the promise type each find any declarations, the program is ill-formed.
+  // [Note 1: If return_­void is found, flowing off the end of a coroutine is
+  // equivalent to a co_­return with no operand. Otherwise, flowing off the end
+  // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
+  // end note]
   bool HasRVoid, HasRValue;
   LookupResult LRVoid =
   lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
@@ -1455,18 +1459,20 @@
 << LRValue.getLookupName();
 return false;
   } else if (!HasRVoid && !HasRValue) {
-// FIXME: The PDTS currently specifies this case as UB, not ill-formed.
-// However we still diagnose this as an error since until the PDTS is fixed.
-S.Diag(FD.getLocation(),
-   

[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Chuanqi Xu via Phabricator via cfe-commits
ChuanqiXu added inline comments.



Comment at: clang/test/SemaCXX/coroutines.cpp:987
+//
+// So it isn't ill-formed if the promise doesn't define return_value and 
return_void. It is just a UB.
+coro no_return_value_or_return_void() {

Quuxplusone wrote:
> It's not UB; it's //potential// UB.
> My understanding is that such a coroutine could still be used:
> - if it exits by throwing an exception instead of `co_return`'ing
> - if it suspends and then its caller `destroy`s it instead of `resume`ing it
> 
> I believe it would be useful to have some actual tests for these scenarios, 
> that would actually run and check that the runtime behavior is correct, or at 
> least check the IR that was generated. Is that possible?
Yes, such a coroutine could still be used. AFAIK, we couldn't make tests which 
would run actually. All the test cases I know is about pattern match. So we 
couldn't make tests in clang to run actually for this. I have tested it 
locally. And I think it is unnecessary to check the IR was generated since this 
patch didn't add new statements except a null statement as marker.

BTW, it shows another big issue for coroutines. We lack test-suite and 
benchmarks now. Now I tested the correctness of the compiler by test it in our 
internal projects. But we need an open source test suites absolutely. This is 
true for benchmarks. I thought to make the two things... but I don't find time 
for it now...


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116204/new/

https://reviews.llvm.org/D116204

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Chuanqi Xu via Phabricator via cfe-commits
ChuanqiXu updated this revision to Diff 396126.
ChuanqiXu added a comment.

Address comments


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116204/new/

https://reviews.llvm.org/D116204

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaCoroutine.cpp
  clang/test/SemaCXX/coroutines-exp-namespace.cpp
  clang/test/SemaCXX/coroutines.cpp

Index: clang/test/SemaCXX/coroutines.cpp
===
--- clang/test/SemaCXX/coroutines.cpp
+++ clang/test/SemaCXX/coroutines.cpp
@@ -970,19 +970,36 @@
   co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
 }
 
-struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
-  coro get_return_object();
+struct promise_no_return_func {
+  coro get_return_object();
   suspend_always initial_suspend();
   suspend_always final_suspend() noexcept;
   void unhandled_exception();
 };
-// FIXME: The PDTS currently specifies this as UB, technically forbidding a
-// diagnostic.
-coro no_return_value_or_return_void() {
-  // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
+// [dcl.fct.def.coroutine]/p6
+// If searches for the names return_­void and return_­value in the scope of
+// the promise type each find any declarations, the program is ill-formed.
+// [Note 1: If return_­void is found, flowing off the end of a coroutine is
+// equivalent to a co_­return with no operand. Otherwise, flowing off the end
+// of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
+// end note]
+//
+// So it isn't ill-formed if the promise doesn't define return_value and return_void.
+// It is just a potential UB.
+coro no_return_value_or_return_void() {
   co_await a;
 }
 
+// The following two tests that it would emit correct diagnostic message
+// if we co_return in `promise_no_return_func`.
+coro no_return_value_or_return_void_2() {
+  co_return; // expected-error {{no member named 'return_void'}}
+}
+
+coro no_return_value_or_return_void_3() {
+  co_return 43; // expected-error {{no member named 'return_value'}}
+}
+
 struct bad_await_suspend_return {
   bool await_ready();
   // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Index: clang/test/SemaCXX/coroutines-exp-namespace.cpp
===
--- clang/test/SemaCXX/coroutines-exp-namespace.cpp
+++ clang/test/SemaCXX/coroutines-exp-namespace.cpp
@@ -978,19 +978,6 @@
   co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
 }
 
-struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
-  coro get_return_object();
-  suspend_always initial_suspend();
-  suspend_always final_suspend() noexcept;
-  void unhandled_exception();
-};
-// FIXME: The PDTS currently specifies this as UB, technically forbidding a
-// diagnostic.
-coro no_return_value_or_return_void() {
-  // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
-  co_await a;
-}
-
 struct bad_await_suspend_return {
   bool await_ready();
   // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Index: clang/lib/Sema/SemaCoroutine.cpp
===
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -1391,9 +1391,13 @@
   assert(!IsPromiseDependentType &&
  "cannot make statement while the promise type is dependent");
 
-  // [dcl.fct.def.coroutine]/4
-  // The unqualified-ids 'return_void' and 'return_value' are looked up in
-  // the scope of class P. If both are found, the program is ill-formed.
+  // [dcl.fct.def.coroutine]/p6
+  // If searches for the names return_­void and return_­value in the scope of
+  // the promise type each find any declarations, the program is ill-formed.
+  // [Note 1: If return_­void is found, flowing off the end of a coroutine is
+  // equivalent to a co_­return with no operand. Otherwise, flowing off the end
+  // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
+  // end note]
   bool HasRVoid, HasRValue;
   LookupResult LRVoid =
   lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
@@ -1414,18 +1418,20 @@
 << LRValue.getLookupName();
 return false;
   } else if (!HasRVoid && !HasRValue) {
-// FIXME: The PDTS currently specifies this case as UB, not ill-formed.
-// However we still diagnose this as an error since until the PDTS is fixed.
-S.Diag(FD.getLocation(),
-   diag::err_coroutine_promise_requires_return_function)
-<< PromiseRecordDecl;
-S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
-<< PromiseRecordDecl;
-return false;
+// 

[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/test/SemaCXX/coroutines.cpp:987
+//
+// So it isn't ill-formed if the promise doesn't define return_value and 
return_void. It is just a UB.
+coro no_return_value_or_return_void() {

It's not UB; it's //potential// UB.
My understanding is that such a coroutine could still be used:
- if it exits by throwing an exception instead of `co_return`'ing
- if it suspends and then its caller `destroy`s it instead of `resume`ing it

I believe it would be useful to have some actual tests for these scenarios, 
that would actually run and check that the runtime behavior is correct, or at 
least check the IR that was generated. Is that possible?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116204/new/

https://reviews.llvm.org/D116204

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan accepted this revision.
urnathan added a comment.
This revision is now accepted and ready to land.

looks good!  Yay, Halting Problem :)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116204/new/

https://reviews.llvm.org/D116204

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Chuanqi Xu via Phabricator via cfe-commits
ChuanqiXu updated this revision to Diff 396009.
ChuanqiXu marked 2 inline comments as done.
ChuanqiXu added a comment.

Address comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116204/new/

https://reviews.llvm.org/D116204

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaCoroutine.cpp
  clang/test/SemaCXX/coroutines-exp-namespace.cpp
  clang/test/SemaCXX/coroutines.cpp

Index: clang/test/SemaCXX/coroutines.cpp
===
--- clang/test/SemaCXX/coroutines.cpp
+++ clang/test/SemaCXX/coroutines.cpp
@@ -970,19 +970,34 @@
   co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
 }
 
-struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
-  coro get_return_object();
+struct promise_no_return_func {
+  coro get_return_object();
   suspend_always initial_suspend();
   suspend_always final_suspend() noexcept;
   void unhandled_exception();
 };
-// FIXME: The PDTS currently specifies this as UB, technically forbidding a
-// diagnostic.
-coro no_return_value_or_return_void() {
-  // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
+// [dcl.fct.def.coroutine]/p6
+// If searches for the names return_­void and return_­value in the scope of
+// the promise type each find any declarations, the program is ill-formed.
+// [Note 1: If return_­void is found, flowing off the end of a coroutine is
+// equivalent to a co_­return with no operand. Otherwise, flowing off the end
+// of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
+// end note]
+//
+// So it isn't ill-formed if the promise doesn't define return_value and return_void. It is just a UB.
+coro no_return_value_or_return_void() {
   co_await a;
 }
 
+// The following two tests that it would emit correct warning if we co_return in `promise_no_return_func`.
+coro no_return_value_or_return_void_2() {
+  co_return; // expected-error {{no member named 'return_void'}}
+}
+
+coro no_return_value_or_return_void_3() {
+  co_return 43; // expected-error {{no member named 'return_value'}}
+}
+
 struct bad_await_suspend_return {
   bool await_ready();
   // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Index: clang/test/SemaCXX/coroutines-exp-namespace.cpp
===
--- clang/test/SemaCXX/coroutines-exp-namespace.cpp
+++ clang/test/SemaCXX/coroutines-exp-namespace.cpp
@@ -978,19 +978,6 @@
   co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
 }
 
-struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
-  coro get_return_object();
-  suspend_always initial_suspend();
-  suspend_always final_suspend() noexcept;
-  void unhandled_exception();
-};
-// FIXME: The PDTS currently specifies this as UB, technically forbidding a
-// diagnostic.
-coro no_return_value_or_return_void() {
-  // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
-  co_await a;
-}
-
 struct bad_await_suspend_return {
   bool await_ready();
   // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Index: clang/lib/Sema/SemaCoroutine.cpp
===
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -1391,9 +1391,13 @@
   assert(!IsPromiseDependentType &&
  "cannot make statement while the promise type is dependent");
 
-  // [dcl.fct.def.coroutine]/4
-  // The unqualified-ids 'return_void' and 'return_value' are looked up in
-  // the scope of class P. If both are found, the program is ill-formed.
+  // [dcl.fct.def.coroutine]/p6
+  // If searches for the names return_­void and return_­value in the scope of
+  // the promise type each find any declarations, the program is ill-formed.
+  // [Note 1: If return_­void is found, flowing off the end of a coroutine is
+  // equivalent to a co_­return with no operand. Otherwise, flowing off the end
+  // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
+  // end note]
   bool HasRVoid, HasRValue;
   LookupResult LRVoid =
   lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);
@@ -1414,18 +1418,20 @@
 << LRValue.getLookupName();
 return false;
   } else if (!HasRVoid && !HasRValue) {
-// FIXME: The PDTS currently specifies this case as UB, not ill-formed.
-// However we still diagnose this as an error since until the PDTS is fixed.
-S.Diag(FD.getLocation(),
-   diag::err_coroutine_promise_requires_return_function)
-<< PromiseRecordDecl;
-S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
-<< PromiseRecordDecl;
-return 

[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Chuanqi Xu via Phabricator via cfe-commits
ChuanqiXu marked 2 inline comments as done.
ChuanqiXu added inline comments.



Comment at: clang/lib/Sema/SemaCoroutine.cpp:1431-1432
+//
+// Then AnalysisBasedWarning would emit a warning about `foo()` lacks a
+// co_return statements.
+Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());

urnathan wrote:
> Your testcase doesnt show such a warning.  This seems unhelpful.  
Oh, I need emphasize in the comment that the warning is not correct. I want to 
say that if we don't set `FallThrough`, the compiler would emit incorrect 
warning. And in this revision, we set `FallThrough` so that we could avoid the 
warning. The edited test case could  address this.



Comment at: clang/lib/Sema/SemaCoroutine.cpp:1437-1440
 // If the unqualified-id return_void is found, flowing off the end of a
 // coroutine is equivalent to a co_return with no operand. Otherwise,
 // flowing off the end of a coroutine results in undefined behavior.
 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,

urnathan wrote:
> there's some repetition in the comments.  Perhaps a bloc comment before the 
> if-else sequence?
Yeah, would do.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116204/new/

https://reviews.llvm.org/D116204

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan added inline comments.



Comment at: clang/lib/Sema/SemaCoroutine.cpp:1431-1432
+//
+// Then AnalysisBasedWarning would emit a warning about `foo()` lacks a
+// co_return statements.
+Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());

Your testcase doesnt show such a warning.  This seems unhelpful.  



Comment at: clang/lib/Sema/SemaCoroutine.cpp:1437-1440
 // If the unqualified-id return_void is found, flowing off the end of a
 // coroutine is equivalent to a co_return with no operand. Otherwise,
 // flowing off the end of a coroutine results in undefined behavior.
 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,

there's some repetition in the comments.  Perhaps a bloc comment before the 
if-else sequence?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116204/new/

https://reviews.llvm.org/D116204

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-22 Thread Chuanqi Xu via Phabricator via cfe-commits
ChuanqiXu created this revision.
ChuanqiXu added reviewers: rjmccall, lxfind, Quuxplusone, urnathan.
ChuanqiXu added a project: clang.
ChuanqiXu requested review of this revision.
Herald added a subscriber: cfe-commits.

According to 
[[dcl.fct.def.coroutine]p6](http://eel.is/c++draft/dcl.fct.def.coroutine#6), 
the promise_type is allowed to not define return_void or return_value:

> If searches for the names return_­void and return_­value in the scope of the 
> promise type each find any declarations, the program is ill-formed.
> [Note 1: If return_­void is found, flowing off the end of a coroutine is 
> equivalent to a co_­return with no operand. Otherwise, flowing off the end of 
> a coroutine results in
> undefined behavior ([stmt.return.coroutine]). — end note]




Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D116204

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaCoroutine.cpp
  clang/test/SemaCXX/coroutines-exp-namespace.cpp
  clang/test/SemaCXX/coroutines.cpp

Index: clang/test/SemaCXX/coroutines.cpp
===
--- clang/test/SemaCXX/coroutines.cpp
+++ clang/test/SemaCXX/coroutines.cpp
@@ -970,16 +970,18 @@
   co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
 }
 
-struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
-  coro get_return_object();
+struct promise_no_return_func {
+  coro get_return_object();
   suspend_always initial_suspend();
   suspend_always final_suspend() noexcept;
   void unhandled_exception();
 };
-// FIXME: The PDTS currently specifies this as UB, technically forbidding a
-// diagnostic.
-coro no_return_value_or_return_void() {
-  // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
+// [dcl.fct.def.coroutine]p6:
+// If searches for the names return_­void and return_­value in the scope of the promise type each find any declarations, the program is ill-formed.
+// [Note 1: If return_­void is found, flowing off the end of a coroutine is equivalent to a co_­return with no operand. Otherwise, flowing off the end of a coroutine results in undefined behavior ([stmt.return.coroutine]). — end note]
+//
+// So it isn't ill-formed if the promise doesn't define return_value and return_void. It is just a UB.
+coro no_return_value_or_return_void() {
   co_await a;
 }
 
Index: clang/test/SemaCXX/coroutines-exp-namespace.cpp
===
--- clang/test/SemaCXX/coroutines-exp-namespace.cpp
+++ clang/test/SemaCXX/coroutines-exp-namespace.cpp
@@ -978,19 +978,6 @@
   co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
 }
 
-struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
-  coro get_return_object();
-  suspend_always initial_suspend();
-  suspend_always final_suspend() noexcept;
-  void unhandled_exception();
-};
-// FIXME: The PDTS currently specifies this as UB, technically forbidding a
-// diagnostic.
-coro no_return_value_or_return_void() {
-  // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
-  co_await a;
-}
-
 struct bad_await_suspend_return {
   bool await_ready();
   // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Index: clang/lib/Sema/SemaCoroutine.cpp
===
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -1414,14 +1414,25 @@
 << LRValue.getLookupName();
 return false;
   } else if (!HasRVoid && !HasRValue) {
-// FIXME: The PDTS currently specifies this case as UB, not ill-formed.
-// However we still diagnose this as an error since until the PDTS is fixed.
-S.Diag(FD.getLocation(),
-   diag::err_coroutine_promise_requires_return_function)
-<< PromiseRecordDecl;
-S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
-<< PromiseRecordDecl;
-return false;
+// [stmt.return.coroutine]p3:
+// If p.return_­void() is a valid expression, flowing off the end of a
+// coroutine's function-body is equivalent to a co_­return with no operand;
+// otherwise flowing off the end of a coroutine's function-body results in
+// undefined behavior.
+//
+// We need to set 'Fallthrough' otherwise the other analysis part might
+// think the coroutine has defined a return_value method. So it might emit
+// false positive warning. e.g.,
+//
+//promise_without_return_func foo() {
+//co_await something();
+//}
+//
+// Then AnalysisBasedWarning would emit a warning about `foo()` lacks a
+// co_return statements.
+Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());
+