[clang] Fix out of line Concept-comparisons of NestedNameSpecifiers (PR #65993)

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 12 06:40:19 PDT 2023


https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/65993:

>From 52bcb5537fe67cdb93d50c16de181d87a7bcffc5 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Mon, 11 Sep 2023 11:28:04 -0700
Subject: [PATCH 1/4] Fix out of line Concept-comparisons of
 NestedNameSpecifiers

As reported in GH65810, we don't properly collect ALL of the template
parameters in a nested name specifier, and were only doing the 'inner
level'.

This patch makes sure we collect from all levels.

Fixes: #65810
---
 clang/docs/ReleaseNotes.rst                   |  3 ++
 clang/lib/Sema/SemaTemplateInstantiate.cpp    | 18 ++++---
 .../SemaTemplate/concepts-out-of-line-def.cpp | 48 +++++++++++++++++++
 3 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cc8b2c3808933cb..872c32f59da96ad 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -218,6 +218,9 @@ Bug Fixes in This Version
   (`#65156 <https://github.com/llvm/llvm-project/issues/65156>`_`)
 - Clang no longer considers the loss of ``__unaligned`` qualifier from objects as
   an invalid conversion during method function overload resolution.
+- Clang now properly handles out of line template specializations when there is
+  a non-template inner-class between the function and the class template
+  (`#65810 <https://github.com/llvm/llvm-project/issues/65810>`_).
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 3b1731edec95237..832837556601663 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -231,14 +231,18 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
                                     MultiLevelTemplateArgumentList &Result) {
   if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
     NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
-    const Type *Ty;
-    const TemplateSpecializationType *TSTy;
-    if (NNS && (Ty = NNS->getAsType()) &&
-        (TSTy = Ty->getAs<TemplateSpecializationType>()))
-      Result.addOuterTemplateArguments(const_cast<FunctionTemplateDecl *>(FTD),
-                                       TSTy->template_arguments(),
-                                       /*Final=*/false);
+
+    while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
+
+      if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>())
+        Result.addOuterTemplateArguments(
+            const_cast<FunctionTemplateDecl *>(FTD), TSTy->template_arguments(),
+            /*Final=*/false);
+
+      NNS = NNS->getPrefix();
+    }
   }
+
   return Response::ChangeDecl(FTD->getLexicalDeclContext());
 }
 
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index 4688c28b489307f..f067c02ca48f584 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -418,3 +418,51 @@ template<typename T> concept A = true;
 template<typename T> struct X { A<T> auto f(); };
 template<typename T> A<T> auto X<T>::f() {}
 }
+
+namespace GH65810 {
+template<typename Param>
+concept TrivialConcept =
+requires(Param param) {
+  (void)param;
+};
+
+template <typename T>
+struct Base {
+  class InnerClass;
+};
+
+template <typename T>
+class Base<T>::InnerClass {
+  template <typename Param>
+    requires TrivialConcept<Param>
+    int func(Param param) const;
+};
+
+template <typename T>
+template <typename Param>
+requires TrivialConcept<Param>
+int Base<T>::InnerClass::func(Param param) const {
+  return 0;
+}
+
+template<typename T>
+struct Outermost {
+  struct Middle {
+    template<typename U>
+    struct Innermost {
+      template <typename Param>
+        requires TrivialConcept<Param>
+        int func(Param param) const;
+    };
+  };
+};
+
+template <typename T>
+template <typename U>
+template <typename Param>
+requires TrivialConcept<Param>
+int Outermost<T>::Middle::Innermost<U>::func(Param param) const {
+  return 0;
+}
+
+} // namespace GH65810

>From 7258e884c3a40a797693ca636151afc87e6c05ca Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Mon, 11 Sep 2023 13:59:30 -0700
Subject: [PATCH 2/4] Make sure we add injected template args from the FTD

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

diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 832837556601663..7e1a3e88674dbf2 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -230,6 +230,11 @@ Response HandleFunction(const FunctionDecl *Function,
 Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
                                     MultiLevelTemplateArgumentList &Result) {
   if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
+    Result.addOuterTemplateArguments(
+        const_cast<FunctionTemplateDecl *>(FTD),
+        const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
+        /*Final=*/false);
+
     NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
 
     while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {

>From a5bf5e542440c995a34e1cd715416ade1ab9ddd2 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Mon, 11 Sep 2023 15:30:41 -0700
Subject: [PATCH 3/4] Only add arguments when they participate in depth

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

diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 7e1a3e88674dbf2..c723e47ffca8ecd 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -238,11 +238,12 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
     NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
 
     while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
-
-      if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>())
-        Result.addOuterTemplateArguments(
-            const_cast<FunctionTemplateDecl *>(FTD), TSTy->template_arguments(),
-            /*Final=*/false);
+      if (NNS->isInstantiationDependent()) {
+        if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>())
+          Result.addOuterTemplateArguments(
+              const_cast<FunctionTemplateDecl *>(FTD), TSTy->template_arguments(),
+              /*Final=*/false);
+      }
 
       NNS = NNS->getPrefix();
     }

>From 2b86194353e83600c03af93b65f49a2b81962076 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Tue, 12 Sep 2023 06:40:05 -0700
Subject: [PATCH 4/4] Move release note to C++ section, move period.

---
 clang/docs/ReleaseNotes.rst | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 872c32f59da96ad..23b1fc578c6f462 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -218,9 +218,6 @@ Bug Fixes in This Version
   (`#65156 <https://github.com/llvm/llvm-project/issues/65156>`_`)
 - Clang no longer considers the loss of ``__unaligned`` qualifier from objects as
   an invalid conversion during method function overload resolution.
-- Clang now properly handles out of line template specializations when there is
-  a non-template inner-class between the function and the class template
-  (`#65810 <https://github.com/llvm/llvm-project/issues/65810>`_).
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -278,6 +275,10 @@ Bug Fixes to C++ Support
   (`#65067 <https://github.com/llvm/llvm-project/issues/65067>`_` and
   `#63675 <https://github.com/llvm/llvm-project/issues/63675>`_`)
 
+- Clang now properly handles out of line template specializations when there is
+  a non-template inner-class between the function and the class template.
+  (`#65810 <https://github.com/llvm/llvm-project/issues/65810>`_)
+
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 - Fixed an import failure of recursive friend class template.



More information about the cfe-commits mailing list