diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-14 02:55:32 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-14 02:55:32 +0000 |
commit | c3069d618f4661d923cb1b5c4525b082fce73b04 (patch) | |
tree | dc913bb334487a5751df1fb526a232634d7406c4 /lib | |
parent | 4e26caa0365347eb63d483df29cdf86ca084510c (diff) |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 36 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 5 | ||||
-rw-r--r-- | lib/AST/MicrosoftMangle.cpp | 6 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 28 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 45 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 7 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 13 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 12 |
11 files changed, 163 insertions, 4 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 3abfe22caa..35d4b7a097 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1932,6 +1932,42 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, 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 8daba88ea8..0ebd7da679 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1383,6 +1383,11 @@ void CXXNameMangler::mangleType(const TemplateTypeParmType *T) { 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 ef50899e43..ce53fc2174 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1011,6 +1011,12 @@ void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T) { 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 d96993e7bd..3882f4960a 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1244,6 +1244,34 @@ bool EnumType::classof(const TagType *TT) { 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 ef9704ec85..8a740d4ad8 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -568,6 +568,12 @@ void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, 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) { diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 868458c2a9..6a37482d66 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2713,6 +2713,11 @@ bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType( return false; } +bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType( + const SubstTemplateTypeParmPackType *) { + return false; +} + bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType( const TemplateSpecializationType*) { return false; diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 5f181fb5e1..629dc58958 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -712,6 +712,12 @@ namespace { QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, TemplateTypeParmTypeLoc TL); + /// \brief Transforms an already-substituted template type parameter pack + /// into either itself (if we aren't substituting into its pack expansion) + /// or the appropriate substituted argument. + QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB, + SubstTemplateTypeParmPackTypeLoc TL); + ExprResult TransformCallExpr(CallExpr *CE) { getSema().CallsUndergoingInstantiation.push_back(CE); ExprResult Result = @@ -1024,10 +1030,15 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, "Missing argument pack"); if (getSema().ArgumentPackSubstitutionIndex == -1) { - // FIXME: Variadic templates fun case. - getSema().Diag(TL.getSourceRange().getBegin(), - diag::err_pack_expansion_mismatch_unsupported); - return QualType(); + // We have the template argument pack, but we're not expanding the + // enclosing pack expansion yet. Just save the template argument + // pack for later substitution. + QualType Result + = getSema().Context.getSubstTemplateTypeParmPackType(T, Arg); + SubstTemplateTypeParmPackTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; } assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); @@ -1063,6 +1074,32 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, return Result; } +QualType +TemplateInstantiator::TransformSubstTemplateTypeParmPackType( + TypeLocBuilder &TLB, + SubstTemplateTypeParmPackTypeLoc TL) { + if (getSema().ArgumentPackSubstitutionIndex == -1) { + // We aren't expanding the parameter pack, so just return ourselves. + SubstTemplateTypeParmPackTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType()); + NewTL.setNameLoc(TL.getNameLoc()); + return TL.getType(); + } + + const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack(); + unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex; + assert(Index < ArgPack.pack_size() && "Substitution index out-of-range"); + + QualType Result = ArgPack.pack_begin()[Index].getAsType(); + Result = getSema().Context.getSubstTemplateTypeParmType( + TL.getTypePtr()->getReplacedParameter(), + Result); + SubstTemplateTypeParmTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; +} + /// \brief Perform substitution on the type T with a given set of template /// arguments. /// diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 473dcb7d1f..dc5013c25d 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -456,6 +456,10 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, std::pair<IdentifierInfo *, SourceLocation> FirstPack; bool HaveFirstPack = false; + // FIXME: Variadic templates. Even if we don't expand, we'd still like to + // return the number of expansions back to the caller, perhaps as an + // llvm::Optional, so that it can be embedded in the pack expansion. This + // is important for the multi-level substitution case. for (unsigned I = 0; I != NumUnexpanded; ++I) { // Compute the depth and index for this parameter pack. unsigned Depth; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 43d89e2875..4127d5045a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -3927,6 +3927,13 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType( } template<typename Derived> +QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType( + TypeLocBuilder &TLB, + SubstTemplateTypeParmPackTypeLoc TL) { + return TransformTypeSpecType(TLB, TL); +} + +template<typename Derived> QualType TreeTransform<Derived>::TransformTemplateSpecializationType( TypeLocBuilder &TLB, TemplateSpecializationTypeLoc TL) { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 487e23f19c..edb79ee808 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2997,6 +2997,15 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Replacement); } + case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: { + unsigned Idx = 0; + QualType Parm = GetType(Record[Idx++]); + TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx); + return Context->getSubstTemplateTypeParmPackType( + cast<TemplateTypeParmType>(Parm), + ArgPack); + } + case TYPE_INJECTED_CLASS_NAME: { CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0])); QualType TST = GetType(Record[1]); // probably derivable @@ -3233,6 +3242,10 @@ void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc( SubstTemplateTypeParmTypeLoc TL) { TL.setNameLoc(ReadSourceLocation(Record, Idx)); } +void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc( + SubstTemplateTypeParmPackTypeLoc TL) { + TL.setNameLoc(ReadSourceLocation(Record, Idx)); +} void TypeLocReader::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx)); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index d3b103f56c..52cf3829dc 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -244,6 +244,14 @@ ASTTypeWriter::VisitSubstTemplateTypeParmType( } void +ASTTypeWriter::VisitSubstTemplateTypeParmPackType( + const SubstTemplateTypeParmPackType *T) { + Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record); + Writer.AddTemplateArgument(T->getArgumentPack(), Record); + Code = TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK; +} + +void ASTTypeWriter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { Record.push_back(T->isDependentType()); @@ -491,6 +499,10 @@ void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc( SubstTemplateTypeParmTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } +void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc( + SubstTemplateTypeParmPackTypeLoc TL) { + Writer.AddSourceLocation(TL.getNameLoc(), Record); +} void TypeLocWriter::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record); |