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

This PR is proposing a fix for
https://github.com/llvm/llvm-project/issues/65971.

Previously, given a coroutine like this
```
task foo(int a) {
  co_return;
}
```
Parameter `a` is never used. However, because C++ coroutines move
constructs the variable to a heap allocated coroutine activation frame,
we considered all parameters referenced. When diagnosing unused
parameters, we cannot distinguish if the variable reference was due to
coroutine parameter moves.

Compiler Explorer shows that GCC warns against this case correctly, but
clang does not: https://godbolt.org/z/Wo7dfqeaf

This patch addresses this issue by preserving the original
`ParmVarDecl`'s `Referenced` state.
This commit is contained in:
Yuxuan Chen 2023-11-01 23:03:47 -07:00 committed by GitHub
parent d76b56fd28
commit 858b56e496
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 0 deletions

View File

@ -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();
ExprResult PDRefExpr =
BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
ExprValueKind::VK_LValue, Loc); // FIXME: scope?
PD->setReferenced(DeclReferenced);
if (PDRefExpr.isInvalid())
return false;

View File

@ -0,0 +1,34 @@
// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -verify -std=c++20 %s
#include "Inputs/std-coroutine.h"
struct awaitable {
bool await_ready() noexcept;
void await_resume() noexcept;
void await_suspend(std::coroutine_handle<>) noexcept;
};
struct task : awaitable {
struct promise_type {
task get_return_object() noexcept;
awaitable initial_suspend() noexcept;
awaitable final_suspend() noexcept;
void unhandled_exception() noexcept;
void return_void() noexcept;
};
};
task foo(int a) { // expected-warning{{unused parameter 'a'}}
co_return;
}
task bar(int a, int b) { // expected-warning{{unused parameter 'b'}}
a = a + 1;
co_return;
}
void create_closure() {
auto closure = [](int c) -> task { // expected-warning{{unused parameter 'c'}}
co_return;
};
}