[clang] [Clang] Preserve coroutine parameter referenced state during allocation function lookup (PR #217518)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 20 01:53:13 PDT 2026
https://github.com/Lane0218 updated https://github.com/llvm/llvm-project/pull/217518
>From 24aaf5e20013ea98bf907938f1d93f3d03c9f42e Mon Sep 17 00:00:00 2001
From: Lane0218 <laneljc at qq.com>
Date: Thu, 20 Aug 2026 10:55:51 +0800
Subject: [PATCH 1/2] [Clang] Preserve parameter referenced state during
coroutine allocation
---
clang/lib/Sema/SemaCoroutine.cpp | 5 +++++
.../SemaCXX/warn-unused-parameters-coroutine.cpp | 15 +++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 48ee5cc0b0836..275257bf9f198 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1386,9 +1386,14 @@ static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc,
// Build a reference to the parameter.
auto PDLoc = PD->getLocation();
+ // Preserve the referenced state for unused parameter diagnostics.
+ bool DeclReferenced = PD->isReferenced();
ExprResult PDRefExpr =
S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
ExprValueKind::VK_LValue, PDLoc);
+
+ PD->setReferenced(DeclReferenced);
+
if (PDRefExpr.isInvalid())
return false;
diff --git a/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp b/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp
index fee379d869112..42dd7bf586612 100644
--- a/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp
+++ b/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp
@@ -18,10 +18,25 @@ struct task : awaitable {
};
};
+struct task_with_new {
+ struct promise_type {
+ void *operator new(decltype(sizeof(0)));
+ task_with_new get_return_object();
+ awaitable initial_suspend();
+ awaitable final_suspend() noexcept;
+ void unhandled_exception();
+ void return_void();
+ };
+};
+
task foo(int a) { // expected-warning{{unused parameter 'a'}}
co_return;
}
+task_with_new class_specific_new(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;
>From eac7dc1d5d3505cf3eaa86954eb19d4e02907a2e Mon Sep 17 00:00:00 2001
From: Lane0218 <laneljc at qq.com>
Date: Thu, 20 Aug 2026 16:52:41 +0800
Subject: [PATCH 2/2] fixup! [Clang] Preserve parameter referenced state during
coroutine allocation
Distinguish speculative coroutine argument construction from parameters passed to the selected allocation function or promise constructor. Add regression coverage for both outcomes and a release note.
Assisted-by: OpenAI Codex
---
clang/docs/ReleaseNotes.md | 5 +++++
clang/lib/Sema/SemaCoroutine.cpp | 21 ++++++++++++++++---
.../warn-unused-parameters-coroutine.cpp | 13 ++++++++++++
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index b585161ba3ff4..b3b0f8caeb885 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -225,6 +225,11 @@ features cannot lower the translation-unit ABI level;
- More consistent rendering of Unicode characters in diagnostic messages.
+- Fixed `-Wunused-parameter` to diagnose coroutine parameters that are only
+ considered during allocation function lookup or promise object
+ initialization, while not diagnosing parameters passed to the selected
+ allocation function or promise constructor. (#GH217501)
+
- Fixed bug in `-Wdocumentation` so that it correctly handles explicit
function template instantiations (#64087).
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 275257bf9f198..b5872bcc43868 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -463,6 +463,12 @@ static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise,
return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
}
+static void markCoroutineParametersReferenced(FunctionDecl &FD) {
+ for (auto *PD : FD.parameters())
+ if (!PD->getType()->isDependentType())
+ PD->setReferenced();
+}
+
VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
assert(isa<FunctionDecl>(CurContext) && "not in a function scope");
auto *FD = cast<FunctionDecl>(CurContext);
@@ -556,6 +562,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
VD->setInit(MaybeCreateExprWithCleanups(Result.get()));
VD->setInitStyle(VarDecl::CallInit);
CheckCompleteVariableDeclaration(VD);
+ markCoroutineParametersReferenced(*FD);
}
} else
ActOnUninitializedDecl(VD);
@@ -1449,6 +1456,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
FunctionDecl *OperatorNew = nullptr;
SmallVector<Expr *, 1> PlacementArgs;
+ bool PlacementArgsAreCoroutineParameters = false;
DeclarationName NewName =
S.getASTContext().DeclarationNames.getCXXOperatorName(OO_New);
@@ -1502,8 +1510,11 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
// We don't expect to call to global operator new with (size, p0, …, pn).
// So if we choose to lookup the allocation function in global scope, we
// shouldn't lookup placement arguments.
- if (PromiseContainsNew && !collectPlacementArgs(S, FD, Loc, PlacementArgs))
- return false;
+ if (PromiseContainsNew) {
+ if (!collectPlacementArgs(S, FD, Loc, PlacementArgs))
+ return false;
+ PlacementArgsAreCoroutineParameters = true;
+ }
LookupAllocationFunction();
@@ -1569,6 +1580,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
if (!StdNoThrow)
return false;
PlacementArgs = {StdNoThrow};
+ PlacementArgsAreCoroutineParameters = false;
OperatorNew = nullptr;
LookupAllocationFunction(AllocationFunctionScope::Global);
}
@@ -1655,8 +1667,11 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
isAlignedAllocation(IAP.PassAlignment))
NewArgs.push_back(FrameAlignment);
- if (OperatorNew->getNumParams() > NewArgs.size())
+ if (OperatorNew->getNumParams() > NewArgs.size()) {
llvm::append_range(NewArgs, PlacementArgs);
+ if (PlacementArgsAreCoroutineParameters)
+ markCoroutineParametersReferenced(FD);
+ }
ExprResult NewExpr =
S.BuildCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
diff --git a/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp b/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp
index 42dd7bf586612..f065838e1000a 100644
--- a/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp
+++ b/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp
@@ -8,8 +8,12 @@ struct awaitable {
void await_suspend(std::coroutine_handle<>) noexcept;
};
+struct promise_arg {};
+
struct task : awaitable {
struct promise_type {
+ promise_type();
+ promise_type(promise_arg);
task get_return_object() noexcept;
awaitable initial_suspend() noexcept;
awaitable final_suspend() noexcept;
@@ -18,9 +22,12 @@ struct task : awaitable {
};
};
+struct allocation_arg {};
+
struct task_with_new {
struct promise_type {
void *operator new(decltype(sizeof(0)));
+ void *operator new(decltype(sizeof(0)), allocation_arg);
task_with_new get_return_object();
awaitable initial_suspend();
awaitable final_suspend() noexcept;
@@ -33,10 +40,16 @@ task foo(int a) { // expected-warning{{unused parameter 'a'}}
co_return;
}
+task promise_constructor_uses_parameter(promise_arg a) { co_return; }
+
task_with_new class_specific_new(int a) { // expected-warning{{unused parameter 'a'}}
co_return;
}
+task_with_new allocation_function_uses_parameter(allocation_arg a) {
+ co_return;
+}
+
task bar(int a, int b) { // expected-warning{{unused parameter 'b'}}
a = a + 1;
co_return;
More information about the cfe-commits
mailing list