Replace the representation of template template argument pack
expansions with something that is easier to use correctly: a new
template argment kind, rather than a bit on an existing kind. Update
all of the switch statements that deal with template arguments, fixing
a few latent bugs in the process. I"m happy with this representation,
now.
And, oh look! Template instantiation and deduction work for template
template argument pack expansions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122896 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index b452060..6e7f7c3 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2692,7 +2692,12 @@
case TemplateArgument::Template:
return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
-
+
+ case TemplateArgument::TemplateExpansion:
+ return TemplateArgument(getCanonicalTemplateName(
+ Arg.getAsTemplateOrTemplatePattern()),
+ true);
+
case TemplateArgument::Integral:
return TemplateArgument(*Arg.getAsIntegral(),
getCanonicalType(Arg.getIntegralType()));
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 70c8632..5a94de9 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -301,7 +301,12 @@
return IsStructurallyEquivalent(Context,
Arg1.getAsTemplate(),
Arg2.getAsTemplate());
-
+
+ case TemplateArgument::TemplateExpansion:
+ return IsStructurallyEquivalent(Context,
+ Arg1.getAsTemplateOrTemplatePattern(),
+ Arg2.getAsTemplateOrTemplatePattern());
+
case TemplateArgument::Expression:
return IsStructurallyEquivalent(Context,
Arg1.getAsExpr(), Arg2.getAsExpr());
@@ -1785,7 +1790,16 @@
return TemplateArgument(ToTemplate);
}
-
+
+ case TemplateArgument::TemplateExpansion: {
+ TemplateName ToTemplate
+ = Importer.Import(From.getAsTemplateOrTemplatePattern());
+ if (ToTemplate.isNull())
+ return TemplateArgument();
+
+ return TemplateArgument(ToTemplate, true);
+ }
+
case TemplateArgument::Expression:
if (Expr *ToExpr = Importer.Import(From.getAsExpr()))
return TemplateArgument(ToExpr);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 08272e7..5b82ddd 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -179,7 +179,9 @@
break;
case TemplateArgument::Template:
- if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
+ case TemplateArgument::TemplateExpansion:
+ if (TemplateDecl *Template
+ = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl())
LV = merge(LV, getLVForDecl(Template, F));
break;
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index 7465ea4..65a18aa 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -319,6 +319,10 @@
break;
}
case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ // FIXME: Implement!
+ break;
+
case TemplateArgument::Declaration: {
visitDeclRef(A.getAsDecl());
break;
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 17a9326..63c3197 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -972,7 +972,8 @@
break;
case TemplateArgument::Template:
- VisitTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
break;
case TemplateArgument::Declaration:
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 6eae6a4..de5531f 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -39,7 +39,10 @@
case Template:
return getAsTemplate().isDependent();
-
+
+ case TemplateExpansion:
+ return true;
+
case Declaration:
if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
return DC->isDependentContext();
@@ -70,14 +73,15 @@
case Declaration:
case Integral:
case Pack:
+ case Template:
return false;
+ case TemplateExpansion:
+ return true;
+
case Type:
return isa<PackExpansionType>(getAsType());
-
- case Template:
- return TemplateArg.PackExpansion;
-
+
case Expression:
return isa<PackExpansionExpr>(getAsExpr());
}
@@ -90,6 +94,7 @@
case Null:
case Declaration:
case Integral:
+ case TemplateExpansion:
break;
case Type:
@@ -98,8 +103,7 @@
break;
case Template:
- if (!TemplateArg.PackExpansion &&
- getAsTemplate().containsUnexpandedParameterPack())
+ if (getAsTemplate().containsUnexpandedParameterPack())
return true;
break;
@@ -135,20 +139,22 @@
break;
case Template:
- ID.AddBoolean(TemplateArg.PackExpansion);
+ case TemplateExpansion: {
+ TemplateName Template = getAsTemplateOrTemplatePattern();
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(
- getAsTemplate().getAsTemplateDecl())) {
+ Template.getAsTemplateDecl())) {
ID.AddBoolean(true);
ID.AddInteger(TTP->getDepth());
ID.AddInteger(TTP->getPosition());
ID.AddBoolean(TTP->isParameterPack());
} else {
ID.AddBoolean(false);
- ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
- .getAsVoidPointer());
+ ID.AddPointer(Context.getCanonicalTemplateName(Template)
+ .getAsVoidPointer());
}
break;
+ }
case Integral:
getAsIntegral()->Profile(ID);
@@ -173,13 +179,11 @@
case Null:
case Type:
case Declaration:
- case Expression:
+ case Expression:
+ case Template:
+ case TemplateExpansion:
return TypeOrValue == Other.TypeOrValue;
- case Template:
- return TemplateArg.Template == Other.TemplateArg.Template &&
- TemplateArg.PackExpansion == Other.TemplateArg.PackExpansion;
-
case Integral:
return getIntegralType() == Other.getIntegralType() &&
*getAsIntegral() == *Other.getAsIntegral();
@@ -206,13 +210,14 @@
case Expression:
return cast<PackExpansionExpr>(getAsExpr())->getPattern();
- case Template:
- return TemplateArgument(getAsTemplate(), false);
+ case TemplateExpansion:
+ return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
case Declaration:
case Integral:
case Pack:
case Null:
+ case Template:
return TemplateArgument();
}
@@ -248,13 +253,15 @@
break;
}
- case Template: {
+ case Template:
getAsTemplate().print(Out, Policy);
- if (TemplateArg.PackExpansion)
- Out << "...";
break;
- }
-
+
+ case TemplateExpansion:
+ getAsTemplateOrTemplatePattern().print(Out, Policy);
+ Out << "...";
+ break;
+
case Integral: {
Out << getAsIntegral()->toString(10);
break;
@@ -299,15 +306,18 @@
else
return SourceRange();
- case TemplateArgument::Template: {
- SourceLocation End = getTemplateNameLoc();
- if (getTemplateEllipsisLoc().isValid())
- End = getTemplateEllipsisLoc();
+ case TemplateArgument::Template:
if (getTemplateQualifierRange().isValid())
- return SourceRange(getTemplateQualifierRange().getBegin(), End);
- return SourceRange(getTemplateNameLoc(), End);
- }
-
+ return SourceRange(getTemplateQualifierRange().getBegin(),
+ getTemplateNameLoc());
+ return SourceRange(getTemplateNameLoc());
+
+ case TemplateArgument::TemplateExpansion:
+ if (getTemplateQualifierRange().isValid())
+ return SourceRange(getTemplateQualifierRange().getBegin(),
+ getTemplateEllipsisLoc());
+ return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
@@ -355,13 +365,14 @@
Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
return TemplateArgumentLoc(Pattern, Pattern);
}
-
- case TemplateArgument::Template:
+
+ case TemplateArgument::TemplateExpansion:
return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
getTemplateQualifierRange(),
getTemplateNameLoc());
case TemplateArgument::Declaration:
+ case TemplateArgument::Template:
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
@@ -389,11 +400,11 @@
return DB << Arg.getAsIntegral()->toString(10);
case TemplateArgument::Template:
- DB << Arg.getAsTemplate();
- if (Arg.isPackExpansion())
- DB << "...";
- return DB;
-
+ return DB << Arg.getAsTemplate();
+
+ case TemplateArgument::TemplateExpansion:
+ return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
+
case TemplateArgument::Expression: {
// This shouldn't actually ever happen, so it's okay that we're
// regurgitating an expression here.
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 0969b87..ff0e922 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -2169,6 +2169,11 @@
// This is mangled as <type>.
mangleType(A.getAsTemplate());
break;
+ case TemplateArgument::TemplateExpansion:
+ // This is mangled as Dp <type>.
+ Out << "Dp";
+ mangleType(A.getAsTemplateOrTemplatePattern());
+ break;
case TemplateArgument::Expression:
Out << 'X';
mangleExpression(A.getAsExpr());
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 5ed973b..161908e 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1693,11 +1693,12 @@
addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
break;
- case TemplateArgument::Template: {
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
// [...] the namespaces in which any template template arguments are
// defined; and the classes in which any member templates used as
// template template arguments are defined.
- TemplateName Template = Arg.getAsTemplate();
+ TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
if (ClassTemplateDecl *ClassTemplate
= dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
DeclContext *Ctx = ClassTemplate->getDeclContext();
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 9adcf1c8..2c9a430 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2256,10 +2256,12 @@
break;
case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
// We were given a template template argument. It may not be ill-formed;
// see below.
if (DependentTemplateName *DTN
- = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+ = Arg.getArgument().getAsTemplateOrTemplatePattern()
+ .getAsDependentTemplateName()) {
// We have a template argument such as \c T::template X, which we
// parsed as a template template argument. However, since we now
// know that we need a non-type template argument, convert this
@@ -2273,6 +2275,17 @@
Arg.getTemplateQualifierRange(),
NameInfo);
+ // If we parsed the template argument as a pack expansion, create a
+ // pack expansion expression.
+ if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
+ ExprResult Expansion = ActOnPackExpansion(E,
+ Arg.getTemplateEllipsisLoc());
+ if (Expansion.isInvalid())
+ return true;
+
+ E = Expansion.get();
+ }
+
TemplateArgument Result;
if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
return true;
@@ -2348,6 +2361,7 @@
return true;
case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
if (CheckTemplateArgument(TempParm, Arg))
return true;
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index a72a293..5837ebd 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -168,7 +168,16 @@
// All other combinations are incompatible.
return DeducedTemplateArgument();
-
+
+ case TemplateArgument::TemplateExpansion:
+ if (Y.getKind() == TemplateArgument::TemplateExpansion &&
+ Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(),
+ Y.getAsTemplateOrTemplatePattern()))
+ return X;
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
case TemplateArgument::Expression:
// If we deduced a dependent expression in one case and either an integral
// constant or a declaration in another case, keep the integral constant
@@ -934,7 +943,7 @@
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
-
+
case TemplateArgument::Template:
if (Arg.getKind() == TemplateArgument::Template)
return DeduceTemplateArguments(S, TemplateParams,
@@ -943,6 +952,10 @@
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::TemplateExpansion:
+ llvm_unreachable("caller should handle pack expansions");
+ break;
case TemplateArgument::Declaration:
if (Arg.getKind() == TemplateArgument::Declaration &&
@@ -1282,10 +1295,11 @@
Y.getAsDecl()->getCanonicalDecl();
case TemplateArgument::Template:
- return Context.getCanonicalTemplateName(X.getAsTemplate())
- .getAsVoidPointer() ==
- Context.getCanonicalTemplateName(Y.getAsTemplate())
- .getAsVoidPointer();
+ case TemplateArgument::TemplateExpansion:
+ return Context.getCanonicalTemplateName(
+ X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
+ Context.getCanonicalTemplateName(
+ Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
case TemplateArgument::Integral:
return *X.getAsIntegral() == *Y.getAsIntegral();
@@ -1356,9 +1370,11 @@
}
case TemplateArgument::Template:
- return TemplateArgumentLoc(Arg, SourceRange(), Loc,
- Arg.isPackExpansion()? Loc : SourceLocation());
-
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc);
+
+ case TemplateArgument::TemplateExpansion:
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+
case TemplateArgument::Expression:
return TemplateArgumentLoc(Arg, Arg.getAsExpr());
@@ -3244,7 +3260,9 @@
break;
case TemplateArgument::Template:
- MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(),
+ case TemplateArgument::TemplateExpansion:
+ MarkUsedTemplateParameters(SemaRef,
+ TemplateArg.getAsTemplateOrTemplatePattern(),
OnlyDeduced, Depth, Used);
break;
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 919f2c8..d15f91a 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2123,12 +2123,18 @@
}
case TemplateArgument::Template:
- llvm_unreachable("Unsupported pack expansion of templates");
+ return TemplateArgumentLoc(TemplateArgument(
+ Pattern.getArgument().getAsTemplate(),
+ true),
+ Pattern.getTemplateQualifierRange(),
+ Pattern.getTemplateNameLoc(),
+ EllipsisLoc);
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
case TemplateArgument::Pack:
+ case TemplateArgument::TemplateExpansion:
llvm_unreachable("Pack expansion pattern has no parameter packs");
case TemplateArgument::Type:
@@ -2531,7 +2537,11 @@
case TemplateArgument::Template:
Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
break;
-
+
+ case TemplateArgument::TemplateExpansion:
+ Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+ break;
+
case TemplateArgument::Expression:
Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
break;
@@ -2600,7 +2610,10 @@
Input.getTemplateNameLoc());
return false;
}
-
+
+ case TemplateArgument::TemplateExpansion:
+ llvm_unreachable("Caller should expand pack expansions");
+
case TemplateArgument::Expression: {
// Template argument expressions are not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(getSema(),
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index ed0e58f..3bf51e6 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -3381,6 +3381,12 @@
case TemplateArgument::Template: {
SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+ return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
+ SourceLocation());
+ }
+ case TemplateArgument::TemplateExpansion: {
+ SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
+ SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
EllipsisLoc);
@@ -4216,7 +4222,8 @@
TemplateArgument
ASTReader::ReadTemplateArgument(PerFileData &F,
const RecordData &Record, unsigned &Idx) {
- switch ((TemplateArgument::ArgKind)Record[Idx++]) {
+ TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
+ switch (Kind) {
case TemplateArgument::Null:
return TemplateArgument();
case TemplateArgument::Type:
@@ -4228,10 +4235,10 @@
QualType T = GetType(Record[Idx++]);
return TemplateArgument(Value, T);
}
- case TemplateArgument::Template: {
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
TemplateName Name = ReadTemplateName(Record, Idx);
- bool IsPackExpansion = Record[Idx++];
- return TemplateArgument(Name, IsPackExpansion);
+ return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion);
}
case TemplateArgument::Expression:
return TemplateArgument(ReadExpr(F));
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 44f17e4..2c0239d 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -2889,6 +2889,10 @@
case TemplateArgument::Template:
AddSourceRange(Arg.getTemplateQualifierRange(), Record);
AddSourceLocation(Arg.getTemplateNameLoc(), Record);
+ break;
+ case TemplateArgument::TemplateExpansion:
+ AddSourceRange(Arg.getTemplateQualifierRange(), Record);
+ AddSourceLocation(Arg.getTemplateNameLoc(), Record);
AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record);
break;
case TemplateArgument::Null:
@@ -3176,8 +3180,8 @@
AddTypeRef(Arg.getIntegralType(), Record);
break;
case TemplateArgument::Template:
- AddTemplateName(Arg.getAsTemplate(), Record);
- Record.push_back(Arg.isPackExpansion());
+ case TemplateArgument::TemplateExpansion:
+ AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
break;
case TemplateArgument::Expression:
AddStmt(Arg.getAsExpr());