mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 07:26: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
|
||||
`#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.
|
||||
|
@ -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(),
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user