Skip to content

Commit 498e1c2

Browse files
usx95cor3ntin
andauthored
[coroutine] Create coroutine body in the correct eval context (llvm#78589)
Fixes: llvm#78290 See the bug for more context. ```cpp Gen ACoroutine() { if constexpr (0) // remove it make clang compile. co_return; co_await Gen{}; } ``` We miss symbol of ctor of promise_type if the first coroutine statement happens to be inside the disabled branch of `if constexpr`. This happens because the promise object is built when we see the first coroutine statement which is present in `ExpressionEvaluationContext::DiscardedStatement` context due to `if constexpr (0)`. This makes clang believe that the promise constructor is only odr-used and not really "used". The expr evaluation context for the coroutine body should not be related to the context in which the first coroutine statement appears. We override the context to `PotentiallyEvaluated`. --------- Co-authored-by: cor3ntin <[email protected]>
1 parent 461679f commit 498e1c2

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,9 @@ Bug Fixes in This Version
804804
Objective-C++ property accesses to not be converted to a function call
805805
to the getter in the placement-args of new-expressions.
806806
Fixes (`#65053 <https://github.com/llvm/llvm-project/issues/65053>`_)
807+
- Fix an issue with missing symbol definitions when the first coroutine
808+
statement appears in a discarded ``if constexpr`` branch.
809+
Fixes (`#78290 <https://github.com/llvm/llvm-project/issues/78290>`_)
807810

808811
Bug Fixes to Compiler Builtins
809812
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "clang/AST/StmtCXX.h"
2222
#include "clang/Basic/Builtins.h"
2323
#include "clang/Lex/Preprocessor.h"
24+
#include "clang/Sema/EnterExpressionEvaluationContext.h"
2425
#include "clang/Sema/Initialization.h"
2526
#include "clang/Sema/Overload.h"
2627
#include "clang/Sema/ScopeInfo.h"
@@ -773,6 +774,9 @@ bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
773774

774775
bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
775776
StringRef Keyword) {
777+
// Ignore previous expr evaluation contexts.
778+
EnterExpressionEvaluationContext PotentiallyEvaluated(
779+
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
776780
if (!checkCoroutineContext(*this, KWLoc, Keyword))
777781
return false;
778782
auto *ScopeInfo = getCurFunction();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %clang_cc1 -std=c++20 -ast-dump %s | FileCheck %s
2+
#include "Inputs/std-coroutine.h"
3+
4+
// Github issue: https://github.com/llvm/llvm-project/issues/78290
5+
namespace GH78290 {
6+
class Gen {
7+
public:
8+
class promise_type {
9+
public:
10+
template<typename... Args>
11+
explicit promise_type(Args...) {}
12+
// CHECK: CXXConstructorDecl {{.*}} used promise_type 'void ()' {{.*}}
13+
// CHECK-NEXT: TemplateArgument pack
14+
// CHECK-NEXT: CompoundStmt {{.*}}
15+
Gen get_return_object() { return {}; }
16+
17+
void unhandled_exception() {}
18+
void return_void() {}
19+
std::suspend_always await_transform(Gen gen) { return {}; }
20+
21+
std::suspend_always initial_suspend() { return {}; }
22+
// CHECK: CXXMethodDecl {{.*}} used initial_suspend {{.*}}
23+
std::suspend_always final_suspend() noexcept { return {}; }
24+
// CHECK: CXXMethodDecl {{.*}} used final_suspend {{.*}}
25+
};
26+
};
27+
28+
Gen CoroutineBody() {
29+
if constexpr (0) {
30+
co_await Gen{};
31+
}
32+
co_await Gen{};
33+
}
34+
} // namespace GH78290

0 commit comments

Comments
 (0)