[clang] [Clang] Fix crash on template-specialization (PR #142338)
Mark de Wever via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 3 07:59:05 PDT 2025
https://github.com/mark-de-wever-sonarsource updated https://github.com/llvm/llvm-project/pull/142338
>From 930e073e4d5bfbde8028fbb8330e6b91348cc20b Mon Sep 17 00:00:00 2001
From: Mark de Wever <mark.dewever at sonarsource.com>
Date: Mon, 2 Jun 2025 08:57:59 +0200
Subject: [PATCH 1/2] Fix crash on template-specialization
This applies the name restoration as suggested by Richard Smith.
Fixes: #54279
---
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +++++
clang/test/CodeGenCXX/constructor-init.cpp | 2 +-
clang/test/SemaTemplate/default-arguments.cpp | 9 +++++++++
3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 174c8fc59e4fa..9853466e01496 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -34,6 +34,7 @@
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/TimeProfiler.h"
#include <optional>
@@ -5120,6 +5121,10 @@ bool Sema::addInstantiatedParametersToScope(
// Simple case: not a parameter pack.
assert(FParamIdx < Function->getNumParams());
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ DeclarationName name = FunctionParam->getDeclName();
+ auto _ = llvm::make_scope_exit([&]() {
+ FunctionParam->setDeclName(name);
+ });
FunctionParam->setDeclName(PatternParam->getDeclName());
// If the parameter's type is not dependent, update it to match the type
// in the pattern. They can differ in top-level cv-qualifiers, and we want
diff --git a/clang/test/CodeGenCXX/constructor-init.cpp b/clang/test/CodeGenCXX/constructor-init.cpp
index f191599f360e7..b5f4cc0b3d6c8 100644
--- a/clang/test/CodeGenCXX/constructor-init.cpp
+++ b/clang/test/CodeGenCXX/constructor-init.cpp
@@ -160,7 +160,7 @@ template<typename T> struct X;
// Make sure that the instantiated constructor initializes start and
// end properly.
-// CHECK-LABEL: define linkonce_odr void @_ZN1XIiEC2ERKS0_(ptr {{[^,]*}} %this, ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %other) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1XIiEC2ERKS0_(ptr {{[^,]*}} %this, ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %0) unnamed_addr
// CHECK: {{store.*null}}
// CHECK: {{store.*null}}
// CHECK: ret
diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp
index 5ea34c0254ec1..a366c3d8ab722 100644
--- a/clang/test/SemaTemplate/default-arguments.cpp
+++ b/clang/test/SemaTemplate/default-arguments.cpp
@@ -283,3 +283,12 @@ static_assert(S<short *>().SizeOfT<char>() == sizeof(short *), "");
} // namespace GH68490
#endif
+
+namespace PR54279 {
+// Using a different name for the argument when there is a default argument
+// caused a crash.
+template <typename T> void f(const T &a, int c = 0);
+template <> void f(const int &unused, int) {
+ f(42);
+}
+}
>From 25d0d5dace764977949e91a1a65d81dc79239bb8 Mon Sep 17 00:00:00 2001
From: Mark de Wever <mark.dewever at sonarsource.com>
Date: Tue, 3 Jun 2025 16:58:53 +0200
Subject: [PATCH 2/2] Address review comments
---
clang/docs/ReleaseNotes.rst | 1 +
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 +-
clang/test/SemaTemplate/default-arguments.cpp | 40 +++++++++++++++++++
3 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 32266fce4d3cb..810b725c2a456 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -805,6 +805,7 @@ Bug Fixes to C++ Support
- Clang modules now allow a module and its user to differ on TrivialAutoVarInit*
- Fixed an access checking bug when initializing non-aggregates in default arguments (#GH62444), (#GH83608)
- Fixed a pack substitution bug in deducing class template partial specializations. (#GH53609)
+- Fixed a crash when specializing a template function whose primary template has a default argument (#GH54279) (#GH95420)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 9853466e01496..f926b0458ff9e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5121,9 +5121,9 @@ bool Sema::addInstantiatedParametersToScope(
// Simple case: not a parameter pack.
assert(FParamIdx < Function->getNumParams());
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
- DeclarationName name = FunctionParam->getDeclName();
+ DeclarationName Name = FunctionParam->getDeclName();
auto _ = llvm::make_scope_exit([&]() {
- FunctionParam->setDeclName(name);
+ FunctionParam->setDeclName(Name);
});
FunctionParam->setDeclName(PatternParam->getDeclName());
// If the parameter's type is not dependent, update it to match the type
diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp
index a366c3d8ab722..35ff6daa8a1dd 100644
--- a/clang/test/SemaTemplate/default-arguments.cpp
+++ b/clang/test/SemaTemplate/default-arguments.cpp
@@ -292,3 +292,43 @@ template <> void f(const int &unused, int) {
f(42);
}
}
+
+namespace PR54279 {
+template <int> struct a {};
+namespace b {
+template <int c>
+void e(a<c> &, const int ¢er, double, double, unsigned, bool = 0);
+template <int c> void d(a<c> &, double, double, double, unsigned, bool);
+} // namespace b
+struct g {
+ g(int center = 0);
+ int center;
+};
+namespace b {
+template <> void e(a<3> &, const int &f, double, double, unsigned, bool) {
+ a<3> h;
+ e(h, 0, 0, 0, 0);
+}
+template <> void d(a<0> &, double, double, double, unsigned, bool);
+} // namespace b
+}
+
+namespace PR95420 {
+template <typename _Container>
+constexpr auto
+size(const _Container &__cont) noexcept -> decltype(__cont.size0);
+
+struct A {
+ A* data[2];
+};
+
+template <typename T>
+void f1(unsigned long, const A& f, const A& b = {});
+
+template <>
+void f1<A>(unsigned long size, const A& f, const A& b) { // We also need b
+ f1<A>(0, *f.data[0]); // We still need this line
+
+ size; // Changing the name of size prevents crash
+}
+}
More information about the cfe-commits
mailing list