https://github.com/Lane0218 updated https://github.com/llvm/llvm-project/pull/217518
>From 24aaf5e20013ea98bf907938f1d93f3d03c9f42e Mon Sep 17 00:00:00 2001 From: Lane0218 <[email protected]> Date: Thu, 20 Aug 2026 10:55:51 +0800 Subject: [PATCH 1/3] [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 d0ccfb56061809a304459458c7f8382e01e67818 Mon Sep 17 00:00:00 2001 From: Lane0218 <[email protected]> Date: Thu, 20 Aug 2026 16:52:41 +0800 Subject: [PATCH 2/3] fixup! [Clang] Preserve parameter referenced state during coroutine allocation --- 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; >From 2501a9e37c3da626426b50a985b28b40ce8a8ad0 Mon Sep 17 00:00:00 2001 From: Lane0218 <[email protected]> Date: Sat, 22 Aug 2026 09:55:49 +0800 Subject: [PATCH 3/3] [Clang] Handle variadic coroutine allocation parameters --- clang/lib/Sema/SemaCoroutine.cpp | 17 +++++++++++----- .../warn-unused-parameters-coroutine.cpp | 20 +++++++++++++++++-- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index b5872bcc43868..627ed96522025 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -562,6 +562,9 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { VD->setInit(MaybeCreateExprWithCleanups(Result.get())); VD->setInitStyle(VarDecl::CallInit); CheckCompleteVariableDeclaration(VD); + // The constructor is selected with the coroutine parameter copies as + // arguments. Mark the original parameters as referenced for + // -Wunused-parameter. markCoroutineParametersReferenced(*FD); } } else @@ -1456,7 +1459,8 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { FunctionDecl *OperatorNew = nullptr; SmallVector<Expr *, 1> PlacementArgs; - bool PlacementArgsAreCoroutineParameters = false; + // Track whether PlacementArgs still refer to the coroutine parameters. + bool PlacementArgsFromCoroutine = false; DeclarationName NewName = S.getASTContext().DeclarationNames.getCXXOperatorName(OO_New); @@ -1513,7 +1517,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { if (PromiseContainsNew) { if (!collectPlacementArgs(S, FD, Loc, PlacementArgs)) return false; - PlacementArgsAreCoroutineParameters = true; + PlacementArgsFromCoroutine = true; } LookupAllocationFunction(); @@ -1580,7 +1584,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { if (!StdNoThrow) return false; PlacementArgs = {StdNoThrow}; - PlacementArgsAreCoroutineParameters = false; + PlacementArgsFromCoroutine = false; OperatorNew = nullptr; LookupAllocationFunction(AllocationFunctionScope::Global); } @@ -1667,9 +1671,12 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { isAlignedAllocation(IAP.PassAlignment)) NewArgs.push_back(FrameAlignment); - if (OperatorNew->getNumParams() > NewArgs.size()) { + // getNumParams() does not include an ellipsis, but a variadic allocation + // function still receives the coroutine parameters as placement arguments. + if (OperatorNew->isVariadic() || + OperatorNew->getNumParams() > NewArgs.size()) { llvm::append_range(NewArgs, PlacementArgs); - if (PlacementArgsAreCoroutineParameters) + if (PlacementArgsFromCoroutine) markCoroutineParametersReferenced(FD); } diff --git a/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp b/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp index f065838e1000a..ef0c767dbc802 100644 --- a/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp +++ b/clang/test/SemaCXX/warn-unused-parameters-coroutine.cpp @@ -36,17 +36,33 @@ struct task_with_new { }; }; +struct task_with_variadic_new { + struct promise_type { + void *operator new(decltype(sizeof(0)), ...); + task_with_variadic_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 promise_constructor_uses_parameter(promise_arg a) { co_return; } -task_with_new class_specific_new(int a) { // expected-warning{{unused parameter 'a'}} +task_with_new class_specific_new_fallback( + int a) { // expected-warning{{unused parameter 'a'}} + co_return; +} + +task_with_new placement_allocation_uses_parameter(allocation_arg a) { co_return; } -task_with_new allocation_function_uses_parameter(allocation_arg a) { +task_with_variadic_new variadic_allocation_uses_parameter(int a) { co_return; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
