[clang] [Clang][Sema] Use the correct injected template arguments for partial specializations when collecting multi-level template argument lists (PR #112381)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 15 08:32:34 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Krystian Stasiowski (sdkrystian)
<details>
<summary>Changes</summary>
After #<!-- -->111852 refactored multi-level template argument list collection, the following results in a crash:
```cpp
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:
- (modified) clang/include/clang/AST/DeclTemplate.h (+13-1)
- (modified) clang/lib/AST/DeclTemplate.cpp (+28)
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+2-2)
``````````diff
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())
``````````
</details>
https://github.com/llvm/llvm-project/pull/112381
More information about the cfe-commits
mailing list