mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-30 05:36:07 +00:00
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:
parent
91464e1d6a
commit
bfddbdaff0
@ -275,6 +275,10 @@ Bug Fixes to C++ Support
|
|||||||
(`#65067 <https://github.com/llvm/llvm-project/issues/65067>`_ and
|
(`#65067 <https://github.com/llvm/llvm-project/issues/65067>`_ and
|
||||||
`#63675 <https://github.com/llvm/llvm-project/issues/63675>`_)
|
`#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
|
Bug Fixes to AST Handling
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
- Fixed an import failure of recursive friend class template.
|
- Fixed an import failure of recursive friend class template.
|
||||||
|
@ -230,15 +230,25 @@ Response HandleFunction(const FunctionDecl *Function,
|
|||||||
Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
|
Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
|
||||||
MultiLevelTemplateArgumentList &Result) {
|
MultiLevelTemplateArgumentList &Result) {
|
||||||
if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
|
if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
|
||||||
|
Result.addOuterTemplateArguments(
|
||||||
|
const_cast<FunctionTemplateDecl *>(FTD),
|
||||||
|
const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
|
||||||
|
/*Final=*/false);
|
||||||
|
|
||||||
NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
|
NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
|
||||||
const Type *Ty;
|
|
||||||
const TemplateSpecializationType *TSTy;
|
while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
|
||||||
if (NNS && (Ty = NNS->getAsType()) &&
|
if (NNS->isInstantiationDependent()) {
|
||||||
(TSTy = Ty->getAs<TemplateSpecializationType>()))
|
if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>())
|
||||||
Result.addOuterTemplateArguments(const_cast<FunctionTemplateDecl *>(FTD),
|
Result.addOuterTemplateArguments(
|
||||||
TSTy->template_arguments(),
|
const_cast<FunctionTemplateDecl *>(FTD), TSTy->template_arguments(),
|
||||||
/*Final=*/false);
|
/*Final=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
|
NNS = NNS->getPrefix();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response::ChangeDecl(FTD->getLexicalDeclContext());
|
return Response::ChangeDecl(FTD->getLexicalDeclContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,3 +418,51 @@ template<typename T> concept A = true;
|
|||||||
template<typename T> struct X { A<T> auto f(); };
|
template<typename T> struct X { A<T> auto f(); };
|
||||||
template<typename T> A<T> auto X<T>::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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user