Implement support for non-type template parameter packs whose type is
a pack expansion, e.g., the parameter pack Values in:
template<typename ...Types>
struct Outer {
template<Types ...Values>
struct Inner;
};
This new implementation approach introduces the notion of an
"expanded" non-type template parameter pack, for which we have already
expanded the types of the parameter pack (to, say, "int*, float*",
for Outer<int*, float*>) but have not yet expanded the values. Aside
from creating these expanded non-type template parameter packs, this
patch updates template argument checking and non-type template
parameter pack instantiation to make use of the appropriate types in
the parameter pack.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123845 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 5c66a96..7574332 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1155,13 +1155,21 @@
// TemplateParmPosition.
D->setDepth(Record[Idx++]);
D->setPosition(Record[Idx++]);
- // Rest of NonTypeTemplateParmDecl.
- D->ParameterPack = Record[Idx++];
- if (Record[Idx++]) {
- Expr *DefArg = Reader.ReadExpr(F);
- bool Inherited = Record[Idx++];
- D->setDefaultArgument(DefArg, Inherited);
- }
+ if (D->isExpandedParameterPack()) {
+ void **Data = reinterpret_cast<void **>(D + 1);
+ for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
+ Data[2*I] = Reader.GetType(Record[Idx++]).getAsOpaquePtr();
+ Data[2*I + 1] = GetTypeSourceInfo(Record, Idx);
+ }
+ } else {
+ // Rest of NonTypeTemplateParmDecl.
+ D->ParameterPack = Record[Idx++];
+ if (Record[Idx++]) {
+ Expr *DefArg = Reader.ReadExpr(F);
+ bool Inherited = Record[Idx++];
+ D->setDefaultArgument(DefArg, Inherited);
+ }
+ }
}
void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
@@ -1433,6 +1441,11 @@
D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
QualType(), false, 0);
break;
+ case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK:
+ D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0,
+ 0, QualType(), 0, 0, Record[Idx++],
+ 0);
+ break;
case DECL_TEMPLATE_TEMPLATE_PARM:
D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0,
false, 0, 0);
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index c329711..507c669 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -988,18 +988,33 @@
}
void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ // For an expanded parameter pack, record the number of expansion types here
+ // so that it's easier for
+ if (D->isExpandedParameterPack())
+ Record.push_back(D->getNumExpansionTypes());
+
VisitVarDecl(D);
// TemplateParmPosition.
Record.push_back(D->getDepth());
Record.push_back(D->getPosition());
- // Rest of NonTypeTemplateParmDecl.
- Record.push_back(D->isParameterPack());
- Record.push_back(D->getDefaultArgument() != 0);
- if (D->getDefaultArgument()) {
- Writer.AddStmt(D->getDefaultArgument());
- Record.push_back(D->defaultArgumentWasInherited());
+
+ if (D->isExpandedParameterPack()) {
+ for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
+ Writer.AddTypeRef(D->getExpansionType(I), Record);
+ Writer.AddTypeSourceInfo(D->getExpansionTypeSourceInfo(I), Record);
+ }
+
+ Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
+ } else {
+ // Rest of NonTypeTemplateParmDecl.
+ Record.push_back(D->isParameterPack());
+ Record.push_back(D->getDefaultArgument() != 0);
+ if (D->getDefaultArgument()) {
+ Writer.AddStmt(D->getDefaultArgument());
+ Record.push_back(D->defaultArgumentWasInherited());
+ }
+ Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
}
- Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
}
void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {