[clang] [Clang] prevent assertion failure from an invalid template instantiation pattern when adding instantiated params to the scope in friend functions with defaulted params (PR #113777)

Oleksandr T. via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 1 16:30:26 PDT 2024


https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/113777

>From 78019b9d9dc138f38bb5b32576b621351ae6427c Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Sun, 27 Oct 2024 01:07:57 +0300
Subject: [PATCH 1/2] [Clang] prevent assertion failure from an invalid
 template instantiation pattern when adding instantiated params to the scope
 in friend functions with defaulted params

---
 clang/docs/ReleaseNotes.rst                | 2 ++
 clang/lib/Sema/SemaTemplateInstantiate.cpp | 8 ++++----
 clang/test/CXX/temp/temp.res/p4.cpp        | 7 +++++++
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6a95337815174b..428ec8c87a432e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -561,6 +561,8 @@ Bug Fixes to C++ Support
   const-default-constructible even if a union member has a default member initializer.
   (#GH95854).
 - Fixed an assertion failure when evaluating an invalid expression in an array initializer (#GH112140)
+- Fixed an assertion failure caused by an invalid template instantiation pattern
+  for adding instantiated parameters to the scope in friend functions with defaulted parameters. (#GH113324).
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 6a55861fe5af3b..cddfcc48312042 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3435,10 +3435,10 @@ bool Sema::SubstDefaultArgument(
       //   template<typename T> void f(T a, int = decltype(a)());
       //   void g() { f(0); }
       LIS = std::make_unique<LocalInstantiationScope>(*this);
-      FunctionDecl *PatternFD = FD->getTemplateInstantiationPattern(
-          /*ForDefinition*/ false);
-      if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
-        return true;
+      if (FunctionDecl *PatternFD =
+              FD->getTemplateInstantiationPattern(/*ForDefinition*/ false))
+        if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
+          return true;
     }
 
     runWithSufficientStackSpace(Loc, [&] {
diff --git a/clang/test/CXX/temp/temp.res/p4.cpp b/clang/test/CXX/temp/temp.res/p4.cpp
index f54d8649f5da88..62bd766e7e1140 100644
--- a/clang/test/CXX/temp/temp.res/p4.cpp
+++ b/clang/test/CXX/temp/temp.res/p4.cpp
@@ -185,3 +185,10 @@ template<typename T> struct S {
   friend void X::f(T::type);
 };
 }
+
+namespace GH113324 {
+template <typename = int> struct ct {
+  friend void f(ct, int = 0); // expected-error {{friend declaration specifying a default argument must be a definition}}
+};
+void test() { f(ct<>{}); }
+}

>From 89bbd61af02e7bada9bf9482f3fba8e28a475cbe Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Fri, 1 Nov 2024 18:22:34 +0200
Subject: [PATCH 2/2] eliminate nested conditions

---
 clang/lib/Sema/SemaTemplateInstantiate.cpp | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index cddfcc48312042..046ca63e26dbc0 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3428,17 +3428,19 @@ bool Sema::SubstDefaultArgument(
     ContextRAII SavedContext(*this, FD);
     std::unique_ptr<LocalInstantiationScope> LIS;
 
-    if (ForCallExpr) {
+    FunctionDecl *PatternFD =
+        ForCallExpr
+            ? FD->getTemplateInstantiationPattern(/*ForDefinition*/ false)
+            : nullptr;
+    if (PatternFD) {
       // When instantiating a default argument due to use in a call expression,
       // an instantiation scope that includes the parameters of the callee is
       // required to satisfy references from the default argument. For example:
       //   template<typename T> void f(T a, int = decltype(a)());
       //   void g() { f(0); }
       LIS = std::make_unique<LocalInstantiationScope>(*this);
-      if (FunctionDecl *PatternFD =
-              FD->getTemplateInstantiationPattern(/*ForDefinition*/ false))
-        if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
-          return true;
+      if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
+        return true;
     }
 
     runWithSufficientStackSpace(Loc, [&] {



More information about the cfe-commits mailing list