[clang] 498e1c2 - [coroutine] Create coroutine body in the correct eval context (#78589)

via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 18 23:23:29 PST 2024


Author: Utkarsh Saxena
Date: 2024-01-19T08:23:25+01:00
New Revision: 498e1c2257da552abc58aa75f6b9f776bf826f86

URL: https://github.com/llvm/llvm-project/commit/498e1c2257da552abc58aa75f6b9f776bf826f86
DIFF: https://github.com/llvm/llvm-project/commit/498e1c2257da552abc58aa75f6b9f776bf826f86.diff

LOG: [coroutine] Create coroutine body in the correct eval context (#78589)

Fixes: https://github.com/llvm/llvm-project/issues/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 <corentinjabot at gmail.com>

Added: 
    clang/test/SemaCXX/coroutine-promise-ctor.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaCoroutine.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b400d75095421c7..63f756f30873c64 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -804,6 +804,9 @@ Bug Fixes in This Version
   Objective-C++ property accesses to not be converted to a function call
   to the getter in the placement-args of new-expressions.
   Fixes (`#65053 <https://github.com/llvm/llvm-project/issues/65053>`_)
+- Fix an issue with missing symbol definitions when the first coroutine
+  statement appears in a discarded ``if constexpr`` branch.
+  Fixes (`#78290 <https://github.com/llvm/llvm-project/issues/78290>`_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 0e0f8f67dcd73e1..4e600fd29ee7395 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/StmtCXX.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/EnterExpressionEvaluationContext.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Overload.h"
 #include "clang/Sema/ScopeInfo.h"
@@ -773,6 +774,9 @@ bool Sema::checkFinalSuspendNoThrow(const Stmt *FinalSuspend) {
 
 bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
                                    StringRef Keyword) {
+  // Ignore previous expr evaluation contexts.
+  EnterExpressionEvaluationContext PotentiallyEvaluated(
+      *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
   if (!checkCoroutineContext(*this, KWLoc, Keyword))
     return false;
   auto *ScopeInfo = getCurFunction();

diff  --git a/clang/test/SemaCXX/coroutine-promise-ctor.cpp b/clang/test/SemaCXX/coroutine-promise-ctor.cpp
new file mode 100644
index 000000000000000..7a06299712cb774
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-promise-ctor.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++20 -ast-dump %s | FileCheck %s
+#include "Inputs/std-coroutine.h"
+
+// Github issue: https://github.com/llvm/llvm-project/issues/78290
+namespace GH78290 {
+class Gen {
+   public:
+    class promise_type {
+       public:
+        template<typename... Args>
+        explicit promise_type(Args...) {}
+        // CHECK:       CXXConstructorDecl {{.*}} used promise_type 'void ()' {{.*}}
+        // CHECK-NEXT:     TemplateArgument pack
+        // CHECK-NEXT:     CompoundStmt {{.*}}
+        Gen get_return_object() { return {}; }
+
+        void unhandled_exception() {}
+        void return_void() {}
+        std::suspend_always await_transform(Gen gen) { return {}; }
+
+        std::suspend_always initial_suspend() { return {}; }
+        // CHECK: CXXMethodDecl {{.*}} used initial_suspend {{.*}}
+        std::suspend_always final_suspend() noexcept { return {}; }
+        // CHECK: CXXMethodDecl {{.*}} used final_suspend {{.*}}
+    };
+};
+
+Gen CoroutineBody() {
+    if constexpr (0) {
+        co_await Gen{};
+    }
+    co_await Gen{};
+}
+} // namespace GH78290


        


More information about the cfe-commits mailing list