-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[concepts] Extract function template pack arguments from the current instantiation if possible #80594
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Younan Zhang (zyn0217) ChangesBefore the constraint substitution, we employ This may break the contract that, during a tree transformation, in Fixes #72557. Full diff: https://github.com/llvm/llvm-project/pull/80594.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3596109bf044f..4d57ea4fd55b8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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.
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e5999fa50117e..878b557a999e1 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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 *Specializtion =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ Arguments =
+ Specializtion->getTemplateInstantiationArgs().asArray();
+ }
Result.addOuterTemplateArguments(
- const_cast<FunctionTemplateDecl *>(FTD), TSTy->template_arguments(),
+ const_cast<FunctionTemplateDecl *>(FTD), Arguments,
/*Final=*/false);
+ }
}
NNS = NNS->getPrefix();
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index b6fea2e0b4b31..0142efcdc3ee8 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -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
|
Before the constraint substitution, we employ
getTemplateInstantiationArgs
, which in turn attempts to inspectTemplateArgument
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 correspondingTemplateArgument
s for anUnexpandedParameterPack
are expected to be ofPack
kinds if we're expanding template parameters.Fixes #72557.