Skip to content

Commit 52bcb55

Browse files
committed
Fix out of line Concept-comparisons of NestedNameSpecifiers
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: llvm#65810
1 parent 6c0b9e3 commit 52bcb55

File tree

3 files changed

+62
-7
lines changed

3 files changed

+62
-7
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ Bug Fixes in This Version
218218
(`#65156 <https://github.com/llvm/llvm-project/issues/65156>`_`)
219219
- Clang no longer considers the loss of ``__unaligned`` qualifier from objects as
220220
an invalid conversion during method function overload resolution.
221+
- Clang now properly handles out of line template specializations when there is
222+
a non-template inner-class between the function and the class template
223+
(`#65810 <https://github.com/llvm/llvm-project/issues/65810>`_).
221224

222225
Bug Fixes to Compiler Builtins
223226
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,18 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
231231
MultiLevelTemplateArgumentList &Result) {
232232
if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
233233
NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
234-
const Type *Ty;
235-
const TemplateSpecializationType *TSTy;
236-
if (NNS && (Ty = NNS->getAsType()) &&
237-
(TSTy = Ty->getAs<TemplateSpecializationType>()))
238-
Result.addOuterTemplateArguments(const_cast<FunctionTemplateDecl *>(FTD),
239-
TSTy->template_arguments(),
240-
/*Final=*/false);
234+
235+
while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
236+
237+
if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>())
238+
Result.addOuterTemplateArguments(
239+
const_cast<FunctionTemplateDecl *>(FTD), TSTy->template_arguments(),
240+
/*Final=*/false);
241+
242+
NNS = NNS->getPrefix();
243+
}
241244
}
245+
242246
return Response::ChangeDecl(FTD->getLexicalDeclContext());
243247
}
244248

clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,51 @@ template<typename T> concept A = true;
418418
template<typename T> struct X { A<T> auto f(); };
419419
template<typename T> A<T> auto X<T>::f() {}
420420
}
421+
422+
namespace GH65810 {
423+
template<typename Param>
424+
concept TrivialConcept =
425+
requires(Param param) {
426+
(void)param;
427+
};
428+
429+
template <typename T>
430+
struct Base {
431+
class InnerClass;
432+
};
433+
434+
template <typename T>
435+
class Base<T>::InnerClass {
436+
template <typename Param>
437+
requires TrivialConcept<Param>
438+
int func(Param param) const;
439+
};
440+
441+
template <typename T>
442+
template <typename Param>
443+
requires TrivialConcept<Param>
444+
int Base<T>::InnerClass::func(Param param) const {
445+
return 0;
446+
}
447+
448+
template<typename T>
449+
struct Outermost {
450+
struct Middle {
451+
template<typename U>
452+
struct Innermost {
453+
template <typename Param>
454+
requires TrivialConcept<Param>
455+
int func(Param param) const;
456+
};
457+
};
458+
};
459+
460+
template <typename T>
461+
template <typename U>
462+
template <typename Param>
463+
requires TrivialConcept<Param>
464+
int Outermost<T>::Middle::Innermost<U>::func(Param param) const {
465+
return 0;
466+
}
467+
468+
} // namespace GH65810

0 commit comments

Comments
 (0)