https://github.com/akash-manna-sky updated 
https://github.com/llvm/llvm-project/pull/217386

>From 437f04688721193b2b619e32657a3ecb299762ba Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Wed, 19 Aug 2026 10:49:53 +0530
Subject: [PATCH 1/4] [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                             |  8 +++++++-
 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, 30 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 64979e07021dc..cc1173a0e619e 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -505,6 +505,12 @@ features cannot lower the translation-unit ABI level;
   to a subobject and is used in a context that requires an implicit conversion.
   (#GH215900)
 
+- 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
@@ -674,4 +680,4 @@ this release by going into the "`clang/docs/`" directory in 
the Clang
 tree.
 
 If you have any questions or comments about Clang, please feel free to
-contact us on the [Discourse forums (Clang Frontend 
category)](https://discourse.llvm.org/c/clang/6).
+contact us on the [Discourse forums (Clang Frontend 
category)](https://discourse.llvm.org/c/clang/6).
\ No newline at end of file
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 8d5ee07c5ad49..f78c03acd720b 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 4e833a7144405c59ba91984f97da0a9fe1410526 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Wed, 19 Aug 2026 23:08:16 +0530
Subject: [PATCH 2/4] Fix missing newline at end of ReleaseNotes.md

---
 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 cc1173a0e619e..58c50ed2a1a1d 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -680,4 +680,4 @@ this release by going into the "`clang/docs/`" directory in 
the Clang
 tree.
 
 If you have any questions or comments about Clang, please feel free to
-contact us on the [Discourse forums (Clang Frontend 
category)](https://discourse.llvm.org/c/clang/6).
\ No newline at end of file
+contact us on the [Discourse forums (Clang Frontend 
category)](https://discourse.llvm.org/c/clang/6).

>From 68a7851d8f2ec6cefa73bf8ab627c6d392044ba8 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Thu, 20 Aug 2026 11:40:28 +0530
Subject: [PATCH 3/4] 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 58c50ed2a1a1d..6ca916cc1699b 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -505,7 +505,7 @@ features cannot lower the translation-unit ABI level;
   to a subobject and is used in a context that requires an implicit conversion.
   (#GH215900)
 
-- 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 26bf4a8f8d067a9ad2beed0ad7120d0995468d33 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Thu, 20 Aug 2026 14:28:57 +0530
Subject: [PATCH 4/4] [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 6ca916cc1699b..5b4a93d45f766 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -508,8 +508,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 f78c03acd720b..ed8b5023b5586 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

Reply via email to