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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits