diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-12-20 02:24:11 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-12-20 02:24:11 +0000 |
commit | 7536dd5e6c99584481b7dab68b7e7d8df9c54054 (patch) | |
tree | b404f8a27369f14746fb159940fda899f9355cae /lib | |
parent | d3d3be9bc717b37366324e9711f1ea22dea42caa (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.cpp | 26 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 9 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/MicrosoftCXXABI.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 60 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 9 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 15 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 8 |
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); } |