Skip to content

Commit

Permalink
[concepts] Extract function template pack arguments from the current …
Browse files Browse the repository at this point in the history
…instantiation if possible (#80594)

Before the constraint substitution, we employ
`getTemplateInstantiationArgs`, which in turn attempts to inspect
`TemplateArgument`s from the function template. For parameter packs from
their parent contexts, we used to extract the arguments from the
specialization type, in which could result in non-canonical argument
types e.g. `PackExpansionType`.

This may break the contract that, during a tree transformation, in
`TreeTransform::TryExpandParameterPacks`, the corresponding
`TemplateArgument`s for an `UnexpandedParameterPack` are expected to be
of `Pack` kinds if we're expanding template parameters.

Fixes #72557.
  • Loading branch information
zyn0217 committed Feb 6, 2024
1 parent 0123cef commit 2c2d291
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ Bug Fixes to C++ Support
Fixes (`#67976 <https://github.com/llvm/llvm-project/issues/67976>`_)
- Fix crash and diagnostic with const qualified member operator new.
Fixes (`#79748 <https://github.com/llvm/llvm-project/issues/79748>`_)
- Fixed a crash where substituting into a requires-expression that involves parameter packs
during the equivalence determination of two constraint expressions.
(`#72557 <https://github.com/llvm/llvm-project/issues/72557>`_)
- Fix a crash when specializing an out-of-line member function with a default
parameter where we did an incorrect specialization of the initialization of
the default parameter.
Expand Down
32 changes: 30 additions & 2 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,38 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,

while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
if (NNS->isInstantiationDependent()) {
if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>())
if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>()) {
ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments();
// Prefer template arguments from the injected-class-type if possible.
// For example,
// ```cpp
// template <class... Pack> struct S {
// template <class T> void foo();
// };
// template <class... Pack> template <class T>
// ^^^^^^^^^^^^^ InjectedTemplateArgs
// They're of kind TemplateArgument::Pack, not of
// TemplateArgument::Type.
// void S<Pack...>::foo() {}
// ^^^^^^^
// TSTy->template_arguments() (which are of PackExpansionType)
// ```
// This meets the contract in
// TreeTransform::TryExpandParameterPacks that the template arguments
// for unexpanded parameters should be of a Pack kind.
if (TSTy->isCurrentInstantiation()) {
auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
Arguments = CTD->getInjectedTemplateArgs();
else if (auto *Specialization =
dyn_cast<ClassTemplateSpecializationDecl>(RD))
Arguments =
Specialization->getTemplateInstantiationArgs().asArray();
}
Result.addOuterTemplateArguments(
const_cast<FunctionTemplateDecl *>(FTD), TSTy->template_arguments(),
const_cast<FunctionTemplateDecl *>(FTD), Arguments,
/*Final=*/false);
}
}

NNS = NNS->getPrefix();
Expand Down
18 changes: 18 additions & 0 deletions clang/test/SemaTemplate/concepts-out-of-line-def.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,21 @@ void S<T>::test(T target, U... value)
}
{}
} // namespace GH74447

namespace GH72557 {

template <typename...>
concept IsAnyOf = true;

template <class... DerTs> struct DerivedCollection {
template <class DerT>
requires IsAnyOf<DerTs...>
unsigned long index();
};

template <class... DerTs>
template <class DerT>
requires IsAnyOf<DerTs...>
unsigned long DerivedCollection<DerTs...>::index() {}

} // namespace GH72557

0 comments on commit 2c2d291

Please sign in to comment.