[clang] [Clang] Preserve coroutine parameter referenced state (PR #70973)

Yuxuan Chen via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 1 22:58:38 PDT 2023


================
@@ -1965,9 +1965,15 @@ bool Sema::buildCoroutineParameterMoves(SourceLocation Loc) {
     if (PD->getType()->isDependentType())
       continue;
 
+    // Preserve the referenced state for unused parameter diagnostics.
+    bool DeclReferenced = PD->isReferenced();
----------------
yuxuanchen1997 wrote:

`PD->isReferenced()` may be true. The order `Sema` processes things is based on how Parser is sending information to it. I can try to explain based on my limited understanding and corroborate with a test case. So please feel free to correct me if I am wrong. 

Let's take a look at this very simple coroutine. Suppose `task` is defined somewhere as a return object. 
```
task foo(int a, int b) {
  a = a + 1;
  co_return;
}
```
Sema is first asked to compile `foo` like a normal function. Decl `a` and `b` are processed normally. When we use `a` in the `a = a + 1` statement, references are setup.

When the parser encounters `co_return`, it calls `Sema::ActOnCoreturn`. 

What `Sema::ActOnCoreturn` (and its siblings handling other `co_` family of statements) does is to call `Sema::ActOnCoroutineBodyStart`. It checks if clang is already treating `foo` as a coroutine. It will find out that, no. We are not compiling `foo` like a coroutine yet, let's perform necessary checks and establish this context. `buildCoroutineParameterMoves` is called as a result. At that time `a` already has references we need to carry along. 

Suppose that our function has subsequent `co_*` statements, `Sema` knows that we already established the context and doesn't build them again.

The aforementioned `foo` coroutine will cause clang ICE if we `assert(!PD->isReferenced())` here.

https://github.com/llvm/llvm-project/pull/70973


More information about the cfe-commits mailing list