https://github.com/akash-manna-sky updated https://github.com/llvm/llvm-project/pull/217386
>From 88b9bd7f8aa8aeec4f19d93a0beb9bca3eee7eaa Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Wed, 19 Aug 2026 10:49:53 +0530 Subject: [PATCH 1/3] [Clang][Sema] Fix crash on default argument added after a parameter pack (#216211) When a redeclaration of a function template (or an out-of-line definition of a member of a class template) adds a default argument, MergeCXXFunctionDecl correctly diagnoses the error but left the rejected default argument attached to the parameter. The DR1344 check that follows then locates "the first defaulted parameter" as getParamDecl(getMinRequiredArguments()), which is wrong when a parameter pack precedes it: packs are skipped by the count but still occupy a parameter slot. The lookup lands on the pack and `assert(NewParam->hasDefaultArg())` fails (or, without assertions, a bogus err_default_arg_makes_ctor_special is emitted). Recover by discarding the rejected default argument after diagnosing, the same recovery already used for other illegal default arguments in this file. The two declarations then agree on getMinRequiredArguments() and the DR1344 check is skipped, as it should be for an addition that was never legal. Fixes #216211 --- clang/docs/ReleaseNotes.md | 6 ++++++ clang/lib/Sema/SemaDeclCXX.cpp | 4 ++++ .../CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp | 10 ++++++++++ .../CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp | 9 +++++++++ 4 files changed, 29 insertions(+) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 3d28f1d4407a5..3cdaafea10b46 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -516,6 +516,12 @@ features cannot lower the translation-unit ABI level; - Fixed an assertion during template argument deduction where a function parameter pack is referenced by other types in the function type. (#GH28877), (#GH213760) +- Fixed a crash when a redeclaration of a function template or an out-of-line + definition of a member of a class template added a default argument to a + parameter that follows a parameter pack (e.g. + `template <typename... T> S::S(T..., int = 10) {}`). Clang now diagnoses the + invalid default argument and discards it instead of asserting. (#GH216211) + #### Bug Fixes to AST Handling - Fixed a non-deterministic ordering of unused local typedefs that made diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e84d35b2b5ecb..4f1a798347fa2 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -624,6 +624,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Diag(PrevForDefaultArgs->getLocation(), diag::note_template_prev_declaration) << false; + // Recover by discarding the default argument. + NewParam->setDefaultArg(nullptr); } else if (New->getTemplateSpecializationKind() != TSK_ImplicitInstantiation && New->getTemplateSpecializationKind() != TSK_Undeclared) { @@ -665,6 +667,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, diag::err_param_default_argument_member_template_redecl) << WhichKind << NewParam->getDefaultArgRange(); + // Recover by discarding the default argument. + NewParam->setDefaultArg(nullptr); } } } diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp index 6014268a18601..b993e3fe0a1ac 100644 --- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp @@ -106,3 +106,13 @@ void main() { } } // namespace pr12724 + +namespace GH216211 { + +struct S { + template <typename... T> S(T..., int); // expected-note{{previous template declaration is here}} +}; +template <typename... T> +S::S(T..., int = 10) {} // expected-error{{default arguments cannot be added to a function template that has already been declared}} + +} // namespace GH216211 diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp index 9ab0b489a2c45..43d69d8764c2a 100644 --- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp @@ -31,3 +31,12 @@ void X0<T>::f(int = 17) { } // expected-error{{cannot be added}} // DR217 + DR205 (reading tea leaves) template<typename T> void X0<T>::Inner::g(int = 17) { } // expected-error{{cannot be added}} + +// GH216211 +template<typename ...T> +struct X1 { + X1(T..., int); +}; + +template<typename ...T> +X1<T...>::X1(T..., int = 17) { } // expected-error{{cannot be added}} >From 661b268c47ea5de932c85f987144a04abb848465 Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Thu, 20 Aug 2026 11:40:28 +0530 Subject: [PATCH 2/3] Address review: "assertion", not "crash", in release note --- clang/docs/ReleaseNotes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 3cdaafea10b46..d9878b0dc223f 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -516,7 +516,7 @@ features cannot lower the translation-unit ABI level; - Fixed an assertion during template argument deduction where a function parameter pack is referenced by other types in the function type. (#GH28877), (#GH213760) -- Fixed a crash when a redeclaration of a function template or an out-of-line +- Fixed an assertion when a redeclaration of a function template or an out-of-line definition of a member of a class template added a default argument to a parameter that follows a parameter pack (e.g. `template <typename... T> S::S(T..., int = 10) {}`). Clang now diagnoses the >From 0edd471f759633743bb3129f79dfdc8a63410056 Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Thu, 20 Aug 2026 14:28:57 +0530 Subject: [PATCH 3/3] [Clang][Sema] Address review: fix the DR1344 parameter lookup instead of discarding the default argument --- clang/docs/ReleaseNotes.md | 3 +-- clang/lib/Sema/SemaDeclCXX.cpp | 14 ++++++-------- .../dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp | 16 ++++++++++++++-- .../dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp | 4 ++-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index d9878b0dc223f..0ff4358574ea7 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -519,8 +519,7 @@ features cannot lower the translation-unit ABI level; - Fixed an assertion when a redeclaration of a function template or an out-of-line definition of a member of a class template added a default argument to a parameter that follows a parameter pack (e.g. - `template <typename... T> S::S(T..., int = 10) {}`). Clang now diagnoses the - invalid default argument and discards it instead of asserting. (#GH216211) + `template <typename... T> S::S(T..., int = 10) {}`). (#GH216211) #### Bug Fixes to AST Handling diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 4f1a798347fa2..ba4147a773a8d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -624,8 +624,6 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Diag(PrevForDefaultArgs->getLocation(), diag::note_template_prev_declaration) << false; - // Recover by discarding the default argument. - NewParam->setDefaultArg(nullptr); } else if (New->getTemplateSpecializationKind() != TSK_ImplicitInstantiation && New->getTemplateSpecializationKind() != TSK_Undeclared) { @@ -665,10 +663,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Diag(NewParam->getLocation(), diag::err_param_default_argument_member_template_redecl) - << WhichKind - << NewParam->getDefaultArgRange(); - // Recover by discarding the default argument. - NewParam->setDefaultArg(nullptr); + << WhichKind << NewParam->getDefaultArgRange(); } } } @@ -683,8 +678,11 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, OldSM = cast<CXXMethodDecl>(Old)->getSpecialMemberKind(); if (NewSM != OldSM) { - ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments()); - assert(NewParam->hasDefaultArg()); + auto It = llvm::find_if(New->parameters(), [](const ParmVarDecl *P) { + return P->hasDefaultArg(); + }); + assert(It != New->param_end()); + ParmVarDecl *NewParam = *It; Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special) << NewParam->getDefaultArgRange() << NewSM; Diag(Old->getLocation(), diag::note_previous_declaration); diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp index b993e3fe0a1ac..091a864b28620 100644 --- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp @@ -110,9 +110,21 @@ void main() { namespace GH216211 { struct S { - template <typename... T> S(T..., int); // expected-note{{previous template declaration is here}} + template <typename... T> S(T..., int); // expected-note{{previous template declaration is here}} expected-note{{previous declaration is here}} }; template <typename... T> -S::S(T..., int = 10) {} // expected-error{{default arguments cannot be added to a function template that has already been declared}} +S::S(T..., int = 10) {} // expected-error{{cannot be added}} expected-error{{makes this constructor a default constructor}} + +struct S2 { + template <typename... T> S2(T..., int, int); // expected-note 2{{previous template declaration is here}} expected-note{{previous declaration is here}} +}; +template <typename... T> +S2::S2(T..., int = 1, int = 2) {} // expected-error 2{{cannot be added}} expected-error{{makes this constructor a default constructor}} + +struct S3 { + template <typename... T> S3(T..., int, int); // expected-note{{previous template declaration is here}} +}; +template <typename... T> +S3::S3(T..., int, int = 2) {} // expected-error{{cannot be added}} } // namespace GH216211 diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp index 43d69d8764c2a..1b871f1f83073 100644 --- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp @@ -35,8 +35,8 @@ void X0<T>::Inner::g(int = 17) { } // expected-error{{cannot be added}} // GH216211 template<typename ...T> struct X1 { - X1(T..., int); + X1(T..., int); // expected-note{{previous declaration is here}} }; template<typename ...T> -X1<T...>::X1(T..., int = 17) { } // expected-error{{cannot be added}} +X1<T...>::X1(T..., int = 17) { } // expected-error{{cannot be added}} expected-error{{makes this constructor a default constructor}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
