Introduce a new type, PackExpansionType, to capture types that are
pack expansions, e.g. given
template<typename... Types> struct tuple;
template<typename... Types>
struct tuple_of_refs {
typedef tuple<Types&...> types;
};
the type of the "types" typedef is a PackExpansionType whose pattern
is Types&.
This commit introduces support for creating pack expansions for
template type arguments, as above, but not for any other kind of pack
expansion, nor for any form of instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122223 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e9d8c0f..9403841 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2216,6 +2216,32 @@
return QualType(T, 0);
}
+QualType ASTContext::getPackExpansionType(QualType Pattern) {
+ llvm::FoldingSetNodeID ID;
+ PackExpansionType::Profile(ID, Pattern);
+
+ assert(Pattern->containsUnexpandedParameterPack() &&
+ "Pack expansions must expand one or more parameter packs");
+ void *InsertPos = 0;
+ PackExpansionType *T
+ = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (T)
+ return QualType(T, 0);
+
+ QualType Canon;
+ if (!Pattern.isCanonical()) {
+ Canon = getPackExpansionType(getCanonicalType(Pattern));
+
+ // Find the insert position again.
+ PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ T = new (*this) PackExpansionType(Pattern, Canon);
+ Types.push_back(T);
+ PackExpansionTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
+}
+
/// CmpProtocolNames - Comparison predicate for sorting protocols
/// alphabetically.
static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index cc485c4..7ff217e 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -707,7 +707,14 @@
}
break;
}
-
+
+ case Type::PackExpansion:
+ if (!IsStructurallyEquivalent(Context,
+ cast<PackExpansionType>(T1)->getPattern(),
+ cast<PackExpansionType>(T2)->getPattern()))
+ return false;
+ break;
+
case Type::ObjCInterface: {
const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1);
const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2);
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 15c3fb2..e12d7e0 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -36,7 +36,7 @@
void printTag(TagDecl *T, std::string &S);
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) \
- void print##CLASS(const CLASS##Type *T, std::string &S);
+ void print##CLASS(const CLASS##Type *T, std::string &S);
#include "clang/AST/TypeNodes.def"
};
}
@@ -668,6 +668,12 @@
S = MyString + ' ' + S;
}
+void TypePrinter::printPackExpansion(const PackExpansionType *T,
+ std::string &S) {
+ print(T->getPattern(), S);
+ S += "...";
+}
+
void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
std::string &S) {
if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 026f6ba..4659831 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -1474,6 +1474,12 @@
mangleType(T->getElementType());
}
+void CXXNameMangler::mangleType(const PackExpansionType *T) {
+ // FIXME: We may need to push this mangling into the callers
+ Out << "sp";
+ mangleType(T->getPattern());
+}
+
void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
mangleSourceName(T->getDecl()->getIdentifier());
}
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index dd2f1cb..aa9046f 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1140,6 +1140,10 @@
"Don't know how to mangle DependentTemplateSpecializationTypes yet!");
}
+void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T) {
+ assert(false && "Don't know how to mangle PackExpansionTypes yet!");
+}
+
void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T) {
assert(false && "Don't know how to mangle TypeOfTypes yet!");
}
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 333d72a..d38d059 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -1045,6 +1045,11 @@
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
while (true) {
ParsedTemplateArgument Arg = ParseTemplateArgument();
+ if (Tok.is(tok::ellipsis)) {
+ SourceLocation EllipsisLoc = ConsumeToken();
+ Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
+ }
+
if (Arg.isInvalid()) {
SkipUntil(tok::comma, tok::greater, true, true);
return true;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5819362..36bb76f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2386,6 +2386,7 @@
// If we have a template parameter pack, check every remaining template
// argument against that template parameter pack.
+ // FIXME: Variadic templates are unimplemented
if ((*Param)->isTemplateParameterPack()) {
Diag(TemplateLoc, diag::err_variadic_templates_unsupported);
return true;
@@ -2640,6 +2641,11 @@
return VisitNestedNameSpecifier(T->getQualifier());
}
+bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType(
+ const PackExpansionType* T) {
+ return Visit(T->getPattern());
+}
+
bool UnnamedLocalNoLinkageFinder::VisitObjCObjectType(const ObjCObjectType *) {
return false;
}
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index da04b62..d4e99e8 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2815,6 +2815,12 @@
OnlyDeduced, Depth, Used);
break;
+ case Type::PackExpansion:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<PackExpansionType>(T)->getPattern(),
+ OnlyDeduced, Depth, Used);
+ break;
+
// None of these types have any template parameters in them.
case Type::Builtin:
case Type::VariableArray:
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index f190b3c..321f383 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===/
#include "clang/Sema/Sema.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
@@ -254,3 +255,62 @@
return true;
}
+ParsedTemplateArgument
+Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
+ SourceLocation EllipsisLoc) {
+ if (Arg.isInvalid())
+ return Arg;
+
+ switch (Arg.getKind()) {
+ case ParsedTemplateArgument::Type: {
+ TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
+ if (Result.isInvalid())
+ return ParsedTemplateArgument();
+
+ return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
+ Arg.getLocation());
+ }
+
+ case ParsedTemplateArgument::NonType:
+ Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
+ << 0;
+ return ParsedTemplateArgument();
+
+ case ParsedTemplateArgument::Template:
+ Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
+ << 1;
+ return ParsedTemplateArgument();
+ }
+ llvm_unreachable("Unhandled template argument kind?");
+ return ParsedTemplateArgument();
+}
+
+TypeResult Sema::ActOnPackExpansion(ParsedType Type,
+ SourceLocation EllipsisLoc) {
+ TypeSourceInfo *TSInfo;
+ GetTypeFromParser(Type, &TSInfo);
+ if (!TSInfo)
+ return true;
+
+ // C++0x [temp.variadic]p5:
+ // The pattern of a pack expansion shall name one or more
+ // parameter packs that are not expanded by a nested pack
+ // expansion.
+ if (!TSInfo->getType()->containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << TSInfo->getTypeLoc().getSourceRange();
+ return true;
+ }
+
+ // Create the pack expansion type and source-location information.
+ QualType Result = Context.getPackExpansionType(TSInfo->getType());
+ TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
+ PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
+ TL.setEllipsisLoc(EllipsisLoc);
+
+ // Copy over the source-location information from the type.
+ memcpy(TL.getNextTypeLoc().getOpaqueData(),
+ TSInfo->getTypeLoc().getOpaqueData(),
+ TSInfo->getTypeLoc().getFullDataSize());
+ return CreateParsedType(Result, TSResult);
+}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index f4a4ae2..a90ea39 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3506,6 +3506,15 @@
}
template<typename Derived>
+QualType TreeTransform<Derived>::TransformPackExpansionType(TypeLocBuilder &TLB,
+ PackExpansionTypeLoc TL) {
+ // FIXME: Implement!
+ getSema().Diag(TL.getEllipsisLoc(),
+ diag::err_pack_expansion_instantiation_unsupported);
+ return QualType();
+}
+
+template<typename Derived>
QualType
TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
ObjCInterfaceTypeLoc TL) {
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 724ebdf..72360e7 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2930,6 +2930,18 @@
return Context->getParenType(InnerType);
}
+ case TYPE_PACK_EXPANSION: {
+ if (Record.size() != 1) {
+ Error("incorrect encoding of pack expansion type");
+ return QualType();
+ }
+ QualType Pattern = GetType(Record[0]);
+ if (Pattern.isNull())
+ return QualType();
+
+ return Context->getPackExpansionType(Pattern);
+ }
+
case TYPE_ELABORATED: {
unsigned Idx = 0;
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
@@ -3229,6 +3241,9 @@
TL.getTypePtr()->getArg(I).getKind(),
Record, Idx));
}
+void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
+ TL.setEllipsisLoc(ReadSourceLocation(Record, Idx));
+}
void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation(Record, Idx));
}
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 26a54b1..345cc8e 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -298,6 +298,11 @@
Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION;
}
+void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) {
+ Writer.AddTypeRef(T->getPattern(), Record);
+ Code = TYPE_PACK_EXPANSION;
+}
+
void ASTTypeWriter::VisitParenType(const ParenType *T) {
Writer.AddTypeRef(T->getInnerType(), Record);
Code = TYPE_PAREN;
@@ -499,6 +504,9 @@
Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(),
TL.getArgLoc(I).getLocInfo(), Record);
}
+void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getEllipsisLoc(), Record);
+}
void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
}