aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-12-20 02:24:11 +0000
committerDouglas Gregor <dgregor@apple.com>2010-12-20 02:24:11 +0000
commit7536dd5e6c99584481b7dab68b7e7d8df9c54054 (patch)
treeb404f8a27369f14746fb159940fda899f9355cae /lib
parentd3d3be9bc717b37366324e9711f1ea22dea42caa (diff)
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
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp26
-rw-r--r--lib/AST/ASTImporter.cpp9
-rw-r--r--lib/AST/TypePrinter.cpp8
-rw-r--r--lib/CodeGen/Mangle.cpp6
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp4
-rw-r--r--lib/Parse/ParseTemplate.cpp5
-rw-r--r--lib/Sema/SemaTemplate.cpp6
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp6
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp60
-rw-r--r--lib/Sema/TreeTransform.h9
-rw-r--r--lib/Serialization/ASTReader.cpp15
-rw-r--r--lib/Serialization/ASTWriter.cpp8
12 files changed, 160 insertions, 2 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e9d8c0f304..94038418df 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2216,6 +2216,32 @@ ASTContext::getDependentTemplateSpecializationType(
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 cc485c47d9..7ff217e334 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -707,7 +707,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
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 15c3fb2fbf..e12d7e0185 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -36,7 +36,7 @@ namespace {
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 @@ void TypePrinter::printDependentTemplateSpecialization(
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 026f6ba3ff..4659831a66 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -1474,6 +1474,12 @@ void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
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 dd2f1cb134..aa9046f981 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1140,6 +1140,10 @@ void MicrosoftCXXNameMangler::mangleType(
"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 333d72a754..d38d0599ac 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -1045,6 +1045,11 @@ bool
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 5819362e76..36bb76fdb3 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2386,6 +2386,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// 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 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType(
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 da04b62198..d4e99e8ad9 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2815,6 +2815,12 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
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 f190b3c774..321f38397d 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 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
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 f4a4ae28cf..a90ea39325 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3506,6 +3506,15 @@ QualType TreeTransform<Derived>::
}
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 724ebdf96c..72360e7416 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2930,6 +2930,18 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
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 @@ void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
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 26a54b1d55..345cc8e74c 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -298,6 +298,11 @@ ASTTypeWriter::VisitDependentTemplateSpecializationType(
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 @@ void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc(
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);
}