[clang] Fix out of line Concept-comparisons of NestedNameSpecifiers (PR #65993)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 11 11:31:23 PDT 2023
llvmbot wrote:
@llvm/pr-subscribers-clang
<details>
<summary>Changes</summary>
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
--
Full diff: https://github.com/llvm/llvm-project/pull/65993.diff
3 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+3)
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+11-7)
- (modified) clang/test/SemaTemplate/concepts-out-of-line-def.cpp (+48)
<pre>
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
</pre>
</details>
https://github.com/llvm/llvm-project/pull/65993
More information about the cfe-commits
mailing list