Skip to content

Commit 9381c6f

Browse files
authored
[Clang][Sema] Use the correct injected template arguments for partial specializations when collecting multi-level template argument lists (#112381)
After #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). Fixes #112222.
1 parent 95c24cb commit 9381c6f

File tree

4 files changed

+211
-123
lines changed

4 files changed

+211
-123
lines changed

clang/include/clang/AST/DeclTemplate.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,11 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
20852085
class ClassTemplatePartialSpecializationDecl
20862086
: public ClassTemplateSpecializationDecl {
20872087
/// The list of template parameters
2088-
TemplateParameterList* TemplateParams = nullptr;
2088+
TemplateParameterList *TemplateParams = nullptr;
2089+
2090+
/// The set of "injected" template arguments used within this
2091+
/// partial specialization.
2092+
TemplateArgument *InjectedArgs = nullptr;
20892093

20902094
/// The class template partial specialization from which this
20912095
/// class template partial specialization was instantiated.
@@ -2132,6 +2136,10 @@ class ClassTemplatePartialSpecializationDecl
21322136
return TemplateParams;
21332137
}
21342138

2139+
/// Retrieve the template arguments list of the template parameter list
2140+
/// of this template.
2141+
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
2142+
21352143
/// \brief All associated constraints of this partial specialization,
21362144
/// including the requires clause and any constraints derived from
21372145
/// constrained-parameters.
@@ -2856,6 +2864,10 @@ class VarTemplatePartialSpecializationDecl
28562864
/// The list of template parameters
28572865
TemplateParameterList *TemplateParams = nullptr;
28582866

2867+
/// The set of "injected" template arguments used within this
2868+
/// partial specialization.
2869+
TemplateArgument *InjectedArgs = nullptr;
2870+
28592871
/// The variable template partial specialization from which this
28602872
/// variable template partial specialization was instantiated.
28612873
///
@@ -2902,6 +2914,10 @@ class VarTemplatePartialSpecializationDecl
29022914
return TemplateParams;
29032915
}
29042916

2917+
/// Retrieve the template arguments list of the template parameter list
2918+
/// of this template.
2919+
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
2920+
29052921
/// \brief All associated constraints of this partial specialization,
29062922
/// including the requires clause and any constraints derived from
29072923
/// constrained-parameters.

clang/lib/AST/DeclTemplate.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,20 @@ SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
11851185
return Range;
11861186
}
11871187

1188+
ArrayRef<TemplateArgument>
1189+
ClassTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
1190+
TemplateParameterList *Params = getTemplateParameters();
1191+
auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
1192+
if (!First->InjectedArgs) {
1193+
auto &Context = getASTContext();
1194+
SmallVector<TemplateArgument, 16> TemplateArgs;
1195+
Context.getInjectedTemplateArgs(Params, TemplateArgs);
1196+
First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
1197+
std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
1198+
}
1199+
return llvm::ArrayRef(First->InjectedArgs, Params->size());
1200+
}
1201+
11881202
//===----------------------------------------------------------------------===//
11891203
// FriendTemplateDecl Implementation
11901204
//===----------------------------------------------------------------------===//
@@ -1535,6 +1549,20 @@ SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
15351549
return Range;
15361550
}
15371551

1552+
ArrayRef<TemplateArgument>
1553+
VarTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
1554+
TemplateParameterList *Params = getTemplateParameters();
1555+
auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
1556+
if (!First->InjectedArgs) {
1557+
auto &Context = getASTContext();
1558+
SmallVector<TemplateArgument, 16> TemplateArgs;
1559+
Context.getInjectedTemplateArgs(Params, TemplateArgs);
1560+
First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
1561+
std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
1562+
}
1563+
return llvm::ArrayRef(First->InjectedArgs, Params->size());
1564+
}
1565+
15381566
static TemplateParameterList *
15391567
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
15401568
// typename T

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ struct TemplateInstantiationArgumentCollecter
237237
if (Innermost)
238238
AddInnermostTemplateArguments(VTPSD);
239239
else if (ForConstraintInstantiation)
240-
AddOuterTemplateArguments(VTPSD, VTPSD->getTemplateArgs().asArray(),
240+
AddOuterTemplateArguments(VTPSD, VTPSD->getInjectedTemplateArgs(),
241241
/*Final=*/false);
242242

243243
if (VTPSD->isMemberSpecialization())
@@ -274,7 +274,7 @@ struct TemplateInstantiationArgumentCollecter
274274
if (Innermost)
275275
AddInnermostTemplateArguments(CTPSD);
276276
else if (ForConstraintInstantiation)
277-
AddOuterTemplateArguments(CTPSD, CTPSD->getTemplateArgs().asArray(),
277+
AddOuterTemplateArguments(CTPSD, CTPSD->getInjectedTemplateArgs(),
278278
/*Final=*/false);
279279

280280
if (CTPSD->isMemberSpecialization())

0 commit comments

Comments
 (0)