[cfe-commits] r123488 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
Douglas Gregor
dgregor at apple.com
Fri Jan 14 14:40:04 PST 2011
Author: dgregor
Date: Fri Jan 14 16:40:04 2011
New Revision: 123488
URL: http://llvm.org/viewvc/llvm-project?rev=123488&view=rev
Log:
Handle substitutions into function parameter packs whose patterns
contain multiple parameter packs at different levels.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jan 14 16:40:04 2011
@@ -3935,7 +3935,8 @@
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,
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Jan 14 16:40:04 2011
@@ -705,7 +705,8 @@
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 @@
}
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 @@
}
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 @@
// 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(),
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Jan 14 16:40:04 2011
@@ -1425,7 +1425,7 @@
}
ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
- return SemaRef.SubstParmVarDecl(D, TemplateArgs);
+ return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional<unsigned>());
}
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jan 14 16:40:04 2011
@@ -494,7 +494,8 @@
/// \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 @@
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 @@
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 @@
// 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 @@
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 @@
if (RetainExpansion) {
ForgetPartiallySubstitutedPackRAII Forget(getDerived());
ParmVarDecl *NewParm
- = getDerived().TransformFunctionTypeParam(OldParm);
+ = getDerived().TransformFunctionTypeParam(OldParm,
+ OrigNumExpansions);
if (!NewParm)
return true;
@@ -3564,9 +3599,9 @@
// 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 @@
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());
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp?rev=123488&r1=123487&r2=123488&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp Fri Jan 14 16:40:04 2011
@@ -66,4 +66,26 @@
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];
}
More information about the cfe-commits
mailing list