Fix out of line Concept-comparisons of NestedNameSpecifiers (#65993)

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
This commit is contained in:
Erich Keane 2023-09-12 06:40:32 -07:00 committed by GitHub
parent 91464e1d6a
commit bfddbdaff0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 7 deletions

View File

@ -275,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.

View File

@ -230,15 +230,25 @@ 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();
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 (NNS->isInstantiationDependent()) {
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());
}

View File

@ -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