diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-05 23:12:31 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-05 23:12:31 +0000 |
commit | 603cfb4da2f7ba08a1c3452c2fbf70585b8e7621 (patch) | |
tree | 5d4d53e48f48770f5b9d1a429ded000d32823925 /lib/Sema/SemaTemplateInstantiate.cpp | |
parent | 8678d44d973989a7af70311572626036219307e2 (diff) |
Initial implementation of function parameter packs. This implementation allows:
1) Declaration of function parameter packs
2) Instantiation of function parameter packs within function types.
3) Template argument deduction of function parameter packs when
matching two function types.
We're missing all of the important template-instantiation logic for
function template definitions, along with template argument deduction
from the argument list of a function call, so don't even think of
trying to use these for real yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122926 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 46d8c1d3d4..7deb7cad3b 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1052,6 +1052,36 @@ TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T, return Instantiator.TransformType(T); } +TypeSourceInfo *Sema::SubstType(TypeLoc TL, + const MultiLevelTemplateArgumentList &Args, + SourceLocation Loc, + DeclarationName Entity) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + + if (TL.getType().isNull()) + return 0; + + if (!TL.getType()->isDependentType() && + !TL.getType()->isVariablyModifiedType()) { + // FIXME: Make a copy of the TypeLoc data here, so that we can + // return a new TypeSourceInfo. Inefficient! + TypeLocBuilder TLB; + TLB.pushFullCopy(TL); + return TLB.getTypeSourceInfo(Context, TL.getType()); + } + + TemplateInstantiator Instantiator(*this, Args, Loc, Entity); + TypeLocBuilder TLB; + TLB.reserve(TL.getFullDataSize()); + QualType Result = Instantiator.TransformType(TLB, TL); + if (Result.isNull()) + return 0; + + return TLB.getTypeSourceInfo(Context, Result); +} + /// Deprecated form of the above. QualType Sema::SubstType(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -1122,8 +1152,34 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, const MultiLevelTemplateArgumentList &TemplateArgs) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); - TypeSourceInfo *NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), - OldParm->getDeclName()); + TypeSourceInfo *NewDI = 0; + + bool WasParameterPack = false; + bool IsParameterPack = false; + TypeLoc OldTL = OldDI->getTypeLoc(); + if (isa<PackExpansionTypeLoc>(OldTL)) { + PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(OldTL); + WasParameterPack = true; + + // We have a function parameter pack. Substitute into the pattern of the + // expansion. + NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs, + OldParm->getLocation(), OldParm->getDeclName()); + if (!NewDI) + return 0; + + if (NewDI->getType()->containsUnexpandedParameterPack()) { + // We still have unexpanded parameter packs, which means that + // our function parameter is still a function parameter pack. + // Therefore, make its type a pack expansion type. + NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc()); + IsParameterPack = true; + } + } else { + NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), + OldParm->getDeclName()); + } + if (!NewDI) return 0; @@ -1153,7 +1209,11 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg()); - CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm); + // FIXME: When OldParm is a parameter pack and NewParm is not a parameter + // pack, we actually have a set of instantiated locations. Maintain this set! + if (!WasParameterPack || IsParameterPack) + CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm); + // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext // can be anything, is this right ? NewParm->setDeclContext(CurContext); |