Start implementing support for substitution into pack expansions that
involve template parameter packs at multiple template levels that
occur within the signatures members of class templates (and partial
specializations thereof). This is a work-in-progress that is deficient
in several ways, notably:
- It only works for template type parameter packs, but we need to
also support non-type template parameter packs and template template
parameter packs.
- It doesn't keep track of the lengths of the substituted argument
packs in the expansion, so it can't properly diagnose length
mismatches.
However, this is a concrete step in the right direction.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123425 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 3abfe22..35d4b7a 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1932,6 +1932,42 @@
return QualType(SubstParm, 0);
}
+/// \brief Retrieve a
+QualType ASTContext::getSubstTemplateTypeParmPackType(
+ const TemplateTypeParmType *Parm,
+ const TemplateArgument &ArgPack) {
+#ifndef NDEBUG
+ for (TemplateArgument::pack_iterator P = ArgPack.pack_begin(),
+ PEnd = ArgPack.pack_end();
+ P != PEnd; ++P) {
+ assert(P->getKind() == TemplateArgument::Type &&"Pack contains a non-type");
+ assert(P->getAsType().isCanonical() && "Pack contains non-canonical type");
+ }
+#endif
+
+ llvm::FoldingSetNodeID ID;
+ SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack);
+ void *InsertPos = 0;
+ if (SubstTemplateTypeParmPackType *SubstParm
+ = SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(SubstParm, 0);
+
+ QualType Canon;
+ if (!Parm->isCanonicalUnqualified()) {
+ Canon = getCanonicalType(QualType(Parm, 0));
+ Canon = getSubstTemplateTypeParmPackType(cast<TemplateTypeParmType>(Canon),
+ ArgPack);
+ SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ SubstTemplateTypeParmPackType *SubstParm
+ = new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon,
+ ArgPack);
+ Types.push_back(SubstParm);
+ SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
+ return QualType(SubstParm, 0);
+}
+
/// \brief Retrieve the template type parameter type for a template
/// parameter or parameter pack with the given depth, index, and (optionally)
/// name.
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 8daba88..0ebd7da 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -1383,6 +1383,11 @@
mangleTemplateParameter(T->getIndex());
}
+// <type> ::= <template-param>
+void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {
+ mangleTemplateParameter(T->getReplacedParameter()->getIndex());
+}
+
// <type> ::= P <type> # pointer-to
void CXXNameMangler::mangleType(const PointerType *T) {
Out << 'P';
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index ef50899..ce53fc2 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -1011,6 +1011,12 @@
assert(false && "Don't know how to mangle TemplateTypeParmTypes yet!");
}
+void MicrosoftCXXNameMangler::mangleType(
+ const SubstTemplateTypeParmPackType *T) {
+ assert(false &&
+ "Don't know how to mangle SubstTemplateTypeParmPackTypes yet!");
+}
+
// <type> ::= <pointer-type>
// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
void MicrosoftCXXNameMangler::mangleType(const PointerType *T) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d96993e..3882f49 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1244,6 +1244,34 @@
return isa<EnumDecl>(TT->getDecl());
}
+SubstTemplateTypeParmPackType::
+SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
+ QualType Canon,
+ const TemplateArgument &ArgPack)
+ : Type(SubstTemplateTypeParmPack, Canon, true, false, true), Replaced(Param),
+ Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size())
+{
+}
+
+TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
+ return TemplateArgument(Arguments, NumArguments);
+}
+
+void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getReplacedParameter(), getArgumentPack());
+}
+
+void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
+ const TemplateTypeParmType *Replaced,
+ const TemplateArgument &ArgPack) {
+ ID.AddPointer(Replaced);
+ ID.AddInteger(ArgPack.pack_size());
+ for (TemplateArgument::pack_iterator P = ArgPack.pack_begin(),
+ PEnd = ArgPack.pack_end();
+ P != PEnd; ++P)
+ ID.AddPointer(P->getAsType().getAsOpaquePtr());
+}
+
bool TemplateSpecializationType::
anyDependentTemplateArguments(const TemplateArgumentListInfo &Args) {
return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size());
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index ef9704e..8a740d4 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -568,6 +568,12 @@
print(T->getReplacementType(), S);
}
+void TypePrinter::printSubstTemplateTypeParmPack(
+ const SubstTemplateTypeParmPackType *T,
+ std::string &S) {
+ printTemplateTypeParm(T->getReplacedParameter(), S);
+}
+
void TypePrinter::printTemplateSpecialization(
const TemplateSpecializationType *T,
std::string &S) {