-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang][Sema] Use the correct injected template arguments for partial specializations when collecting multi-level template argument lists #112381
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
[Clang][Sema] Use the correct injected template arguments for partial specializations when collecting multi-level template argument lists #112381
Conversation
… specializations when collecting multi-level template argument lists
@llvm/pr-subscribers-clang Author: Krystian Stasiowski (sdkrystian) ChangesAfter #111852 refactored multi-level template argument list collection, the following results in a crash: template<typename T, bool B>
struct A;
template<bool B>
struct A<int, B>
{
void f() requires B;
};
template<bool B>
void A<int, B>::f() requires B { } // crash here This happens because when collecting template arguments for constraint normalization from a partial specialization, we incorrectly use the template argument list of the partial specialization. We should be using the template argument list of the template-head (as defined in [[temp.arg.general] p2](http://eel.is/c++draft/temp.arg.general#2)). Fixes #112222. Full diff: https://github.com/llvm/llvm-project/pull/112381.diff 3 Files Affected:
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 141f58c4600af0..6c7f47cd5204c2 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -2085,7 +2085,9 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
class ClassTemplatePartialSpecializationDecl
: public ClassTemplateSpecializationDecl {
/// The list of template parameters
- TemplateParameterList* TemplateParams = nullptr;
+ TemplateParameterList *TemplateParams = nullptr;
+
+ TemplateArgument *InjectedArgs = nullptr;
/// The class template partial specialization from which this
/// class template partial specialization was instantiated.
@@ -2132,6 +2134,10 @@ class ClassTemplatePartialSpecializationDecl
return TemplateParams;
}
+ /// Retrieve the template arguments list of the template parameter list
+ /// of this template.
+ ArrayRef<TemplateArgument> getInjectedTemplateArgs();
+
/// \brief All associated constraints of this partial specialization,
/// including the requires clause and any constraints derived from
/// constrained-parameters.
@@ -2856,6 +2862,8 @@ class VarTemplatePartialSpecializationDecl
/// The list of template parameters
TemplateParameterList *TemplateParams = nullptr;
+ TemplateArgument *InjectedArgs = nullptr;
+
/// The variable template partial specialization from which this
/// variable template partial specialization was instantiated.
///
@@ -2902,6 +2910,10 @@ class VarTemplatePartialSpecializationDecl
return TemplateParams;
}
+ /// Retrieve the template arguments list of the template parameter list
+ /// of this template.
+ ArrayRef<TemplateArgument> getInjectedTemplateArgs();
+
/// \brief All associated constraints of this partial specialization,
/// including the requires clause and any constraints derived from
/// constrained-parameters.
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index d9b67b7bedf5a5..d2d8907b884ec8 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1185,6 +1185,20 @@ SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
return Range;
}
+ArrayRef<TemplateArgument>
+ClassTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
+ TemplateParameterList *Params = getTemplateParameters();
+ auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ if (!First->InjectedArgs) {
+ auto &Context = getASTContext();
+ SmallVector<TemplateArgument, 16> TemplateArgs;
+ Context.getInjectedTemplateArgs(Params, TemplateArgs);
+ First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
+ std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
+ }
+ return llvm::ArrayRef(First->InjectedArgs, Params->size());
+}
+
//===----------------------------------------------------------------------===//
// FriendTemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -1535,6 +1549,20 @@ SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
return Range;
}
+ArrayRef<TemplateArgument>
+VarTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
+ TemplateParameterList *Params = getTemplateParameters();
+ auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ if (!First->InjectedArgs) {
+ auto &Context = getASTContext();
+ SmallVector<TemplateArgument, 16> TemplateArgs;
+ Context.getInjectedTemplateArgs(Params, TemplateArgs);
+ First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
+ std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
+ }
+ return llvm::ArrayRef(First->InjectedArgs, Params->size());
+}
+
static TemplateParameterList *
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// typename T
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 8c7f694c09042e..8665c099903dc3 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -237,7 +237,7 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(VTPSD);
else if (ForConstraintInstantiation)
- AddOuterTemplateArguments(VTPSD, VTPSD->getTemplateArgs().asArray(),
+ AddOuterTemplateArguments(VTPSD, VTPSD->getInjectedTemplateArgs(),
/*Final=*/false);
if (VTPSD->isMemberSpecialization())
@@ -274,7 +274,7 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(CTPSD);
else if (ForConstraintInstantiation)
- AddOuterTemplateArguments(CTPSD, CTPSD->getTemplateArgs().asArray(),
+ AddOuterTemplateArguments(CTPSD, CTPSD->getInjectedTemplateArgs(),
/*Final=*/false);
if (CTPSD->isMemberSpecialization())
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change itself seems reasonable, so approve, pending a good couple of tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG modulo one question. Thanks for the prompt fix.
TemplateParameterList* TemplateParams = nullptr; | ||
TemplateParameterList *TemplateParams = nullptr; | ||
|
||
TemplateArgument *InjectedArgs = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need serialization?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just for caching the injected arguments. If we don't serialize these, they will be just rebuilt anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, like @mizvekov said we don't serialize injected template arguments
… partial specializations when collecting multi-level template argument lists (llvm#112381)" This reverts commit 9381c6f.
After #111852 refactored multi-level template argument list collection, the following results in a crash:
This happens because when collecting template arguments for constraint normalization from a partial specialization, we incorrectly use the template argument list of the partial specialization. We should be using the template argument list of the template-head (as defined in [temp.arg.general] p2). Fixes #112222.
Still need to add tests.