Skip to content

Commit 858b56e

Browse files
[Clang] Preserve coroutine parameter referenced state (#70973)
This PR is proposing a fix for #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.
1 parent d76b56f commit 858b56e

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,9 +1965,15 @@ bool Sema::buildCoroutineParameterMoves(SourceLocation Loc) {
19651965
if (PD->getType()->isDependentType())
19661966
continue;
19671967

1968+
// Preserve the referenced state for unused parameter diagnostics.
1969+
bool DeclReferenced = PD->isReferenced();
1970+
19681971
ExprResult PDRefExpr =
19691972
BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(),
19701973
ExprValueKind::VK_LValue, Loc); // FIXME: scope?
1974+
1975+
PD->setReferenced(DeclReferenced);
1976+
19711977
if (PDRefExpr.isInvalid())
19721978
return false;
19731979

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -verify -std=c++20 %s
2+
3+
#include "Inputs/std-coroutine.h"
4+
5+
struct awaitable {
6+
bool await_ready() noexcept;
7+
void await_resume() noexcept;
8+
void await_suspend(std::coroutine_handle<>) noexcept;
9+
};
10+
11+
struct task : awaitable {
12+
struct promise_type {
13+
task get_return_object() noexcept;
14+
awaitable initial_suspend() noexcept;
15+
awaitable final_suspend() noexcept;
16+
void unhandled_exception() noexcept;
17+
void return_void() noexcept;
18+
};
19+
};
20+
21+
task foo(int a) { // expected-warning{{unused parameter 'a'}}
22+
co_return;
23+
}
24+
25+
task bar(int a, int b) { // expected-warning{{unused parameter 'b'}}
26+
a = a + 1;
27+
co_return;
28+
}
29+
30+
void create_closure() {
31+
auto closure = [](int c) -> task { // expected-warning{{unused parameter 'c'}}
32+
co_return;
33+
};
34+
}

0 commit comments

Comments
 (0)