diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-14 22:40:04 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-14 22:40:04 +0000 |
commit | 6a24bfda084f06a0b252b7befe8cbb17fce7f94e (patch) | |
tree | d8c6f97bb8b00178d8327dbf9a5ee25af3963186 | |
parent | c39b5e867df74904ac7e50d225b3cca0db43571f (diff) |
Handle substitutions into function parameter packs whose patterns
contain multiple parameter packs at different levels.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123488 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 54 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp | 22 |
5 files changed, 79 insertions, 17 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d00a371c22..76b5f523fa 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3935,7 +3935,8 @@ public: SourceLocation Loc, DeclarationName Entity); ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + llvm::Optional<unsigned> NumExpansions); bool SubstParmTypes(SourceLocation Loc, ParmVarDecl **Params, unsigned NumParams, const MultiLevelTemplateArgumentList &TemplateArgs, diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index c181a568b5..13cc17ef53 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -705,7 +705,8 @@ namespace { QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL); - ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm); + ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, + llvm::Optional<unsigned> NumExpansions); /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. @@ -1000,8 +1001,10 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, } ParmVarDecl * -TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm) { - return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs); +TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm, + llvm::Optional<unsigned> NumExpansions) { + return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, + NumExpansions); } QualType @@ -1241,7 +1244,8 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, } ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + llvm::Optional<unsigned> NumExpansions) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; @@ -1260,9 +1264,8 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, // 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. - // FIXME: Variadic templates num expansions. NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(), - llvm::Optional<unsigned>()); + NumExpansions); } } else { NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index bd431a1138..76e7406c51 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1425,7 +1425,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { } ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - return SemaRef.SubstParmVarDecl(D, TemplateArgs); + return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional<unsigned>()); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index d973f82401..4abcb88fc0 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -494,7 +494,8 @@ public: /// \brief Transforms a single function-type parameter. Return null /// on error. - ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm); + ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, + llvm::Optional<unsigned> NumExpansions); QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); @@ -3473,9 +3474,38 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB, template<typename Derived> ParmVarDecl * -TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm) { +TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm, + llvm::Optional<unsigned> NumExpansions) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); - TypeSourceInfo *NewDI = getDerived().TransformType(OldDI); + TypeSourceInfo *NewDI = 0; + + if (NumExpansions && isa<PackExpansionType>(OldDI->getType())) { + // If we're substituting into a pack expansion type and we know the + TypeLoc OldTL = OldDI->getTypeLoc(); + PackExpansionTypeLoc OldExpansionTL = cast<PackExpansionTypeLoc>(OldTL); + + TypeLocBuilder TLB; + TypeLoc NewTL = OldDI->getTypeLoc(); + TLB.reserve(NewTL.getFullDataSize()); + + QualType Result = getDerived().TransformType(TLB, + OldExpansionTL.getPatternLoc()); + if (Result.isNull()) + return 0; + + Result = RebuildPackExpansionType(Result, + OldExpansionTL.getPatternLoc().getSourceRange(), + OldExpansionTL.getEllipsisLoc(), + NumExpansions); + if (Result.isNull()) + return 0; + + PackExpansionTypeLoc NewExpansionTL + = TLB.push<PackExpansionTypeLoc>(Result); + NewExpansionTL.setEllipsisLoc(OldExpansionTL.getEllipsisLoc()); + NewDI = TLB.getTypeSourceInfo(SemaRef.Context, Result); + } else + NewDI = getDerived().TransformType(OldDI); if (!NewDI) return 0; @@ -3502,6 +3532,7 @@ bool TreeTransform<Derived>:: llvm::SmallVectorImpl<ParmVarDecl*> *PVars) { for (unsigned i = 0; i != NumParams; ++i) { if (ParmVarDecl *OldParm = Params[i]) { + llvm::Optional<unsigned> NumExpansions; if (OldParm->isParameterPack()) { // We have a function parameter pack that may need to be expanded. llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; @@ -3515,7 +3546,9 @@ bool TreeTransform<Derived>:: // Determine whether we should expand the parameter packs. bool ShouldExpand = false; bool RetainExpansion = false; - llvm::Optional<unsigned> NumExpansions; + llvm::Optional<unsigned> OrigNumExpansions + = ExpansionTL.getTypePtr()->getNumExpansions(); + NumExpansions = OrigNumExpansions; if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), Pattern.getSourceRange(), Unexpanded.data(), @@ -3533,7 +3566,8 @@ bool TreeTransform<Derived>:: for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); ParmVarDecl *NewParm - = getDerived().TransformFunctionTypeParam(OldParm); + = getDerived().TransformFunctionTypeParam(OldParm, + OrigNumExpansions); if (!NewParm) return true; @@ -3547,7 +3581,8 @@ bool TreeTransform<Derived>:: if (RetainExpansion) { ForgetPartiallySubstitutedPackRAII Forget(getDerived()); ParmVarDecl *NewParm - = getDerived().TransformFunctionTypeParam(OldParm); + = getDerived().TransformFunctionTypeParam(OldParm, + OrigNumExpansions); if (!NewParm) return true; @@ -3564,9 +3599,9 @@ bool TreeTransform<Derived>:: // expansion. } - // FIXME: Variadic templates num expansions Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); - ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm); + ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, + NumExpansions); if (!NewParm) return true; @@ -7053,7 +7088,8 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { for (BlockDecl::param_const_iterator P = BD->param_begin(), EN = BD->param_end(); P != EN; ++P) { ParmVarDecl *OldParm = (*P); - ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm); + ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, + llvm::Optional<unsigned>()); QualType NewType = NewParm->getType(); Params.push_back(NewParm); ParamTypes.push_back(NewParm->getType()); diff --git a/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp index a061104d65..64554ab634 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp @@ -66,4 +66,26 @@ namespace PacksAtDifferentLevels { sizeof(int) + sizeof(unsigned int), sizeof(long) + sizeof(unsigned long)> >::value == 0? 1 : -1]; + + template<typename ...Types> + struct X2 { + template<typename> struct Inner { + static const unsigned value = 1; + }; + + template<typename R, typename ...YTypes> + struct Inner<R(pair<Types, YTypes>...)> { + static const unsigned value = sizeof...(Types) - sizeof...(YTypes); + }; + }; + + int check4[X2<short, int, long>::Inner<int(pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>) + >::value == 0? 1 : -1]; + + int check5[X2<short, int>::Inner<int(pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>) + >::value == 1? 1 : -1]; } |