From d1bb4ae6cbc0f8bea4b329e040f58b18c03388e7 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 25 Jan 2012 16:15:54 +0000 Subject: [PATCH] When we're substituting into a function parameter pack and expect to get a function parameter pack (but don't due to weird substitutions), complain. Fixes the last bit of PR11848. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148960 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 3 ++- lib/Sema/SemaTemplateInstantiate.cpp | 26 ++++++++++++++++-------- lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 ++- lib/Sema/TreeTransform.h | 19 +++++++++++------ test/SemaTemplate/alias-templates.cpp | 5 ++--- 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 30f0de375f..cf77a7e9e5 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5100,7 +5100,8 @@ public: ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, - llvm::Optional NumExpansions); + llvm::Optional NumExpansions, + bool ExpectParameterPack); bool SubstParmTypes(SourceLocation Loc, ParmVarDecl **Params, unsigned NumParams, const MultiLevelTemplateArgumentList &TemplateArgs, diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index e183f1f1c1..dde782672f 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -778,7 +778,8 @@ namespace { FunctionProtoTypeLoc TL); ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional NumExpansions); + llvm::Optional NumExpansions, + bool ExpectParameterPack); /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. @@ -1194,9 +1195,10 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, ParmVarDecl * TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional NumExpansions) { + llvm::Optional NumExpansions, + bool ExpectParameterPack) { return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment, - NumExpansions); + NumExpansions, ExpectParameterPack); } QualType @@ -1450,7 +1452,8 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, - llvm::Optional NumExpansions) { + llvm::Optional NumExpansions, + bool ExpectParameterPack) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; @@ -1471,7 +1474,16 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, // Therefore, make its type a pack expansion type. NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(), NumExpansions); - } + } else if (ExpectParameterPack) { + // We expected to get a parameter pack but didn't (because the type + // itself is not a pack expansion type), so complain. This can occur when + // the substitution goes through an alias template that "loses" the + // pack expansion. + Diag(OldParm->getLocation(), + diag::err_function_parameter_pack_without_parameter_packs) + << NewDI->getType(); + return 0; + } } else { NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), OldParm->getDeclName()); @@ -1506,9 +1518,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, NewParm->setUninstantiatedDefaultArg(Arg); NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg()); - - // 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 (OldParm->isParameterPack() && !NewParm->isParameterPack()) { // Add the new parameter to the instantiated parameter pack. CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index c9d2cf6e18..023005cd19 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1601,7 +1601,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, - llvm::Optional()); + llvm::Optional(), + /*ExpectParameterPack=*/false); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 2ddba4710f..f5fc3b7cb8 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -530,7 +530,8 @@ public: /// scope index; can be negative ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional NumExpansions); + llvm::Optional NumExpansions, + bool ExpectParameterPack); QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); @@ -3814,12 +3815,14 @@ template ParmVarDecl * TreeTransform::TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional NumExpansions) { + llvm::Optional NumExpansions, + bool ExpectParameterPack) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; if (NumExpansions && isa(OldDI->getType())) { // If we're substituting into a pack expansion type and we know the + // length we want to expand to, just substitute for the pattern. TypeLoc OldTL = OldDI->getTypeLoc(); PackExpansionTypeLoc OldExpansionTL = cast(OldTL); @@ -3916,7 +3919,8 @@ bool TreeTransform:: ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, indexAdjustment++, - OrigNumExpansions); + OrigNumExpansions, + /*ExpectParameterPack=*/false); if (!NewParm) return true; @@ -3932,7 +3936,8 @@ bool TreeTransform:: ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, indexAdjustment++, - OrigNumExpansions); + OrigNumExpansions, + /*ExpectParameterPack=*/false); if (!NewParm) return true; @@ -3956,11 +3961,13 @@ bool TreeTransform:: Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); NewParm = getDerived().TransformFunctionTypeParam(OldParm, indexAdjustment, - NumExpansions); + NumExpansions, + /*ExpectParameterPack=*/true); } else { NewParm = getDerived().TransformFunctionTypeParam(OldParm, indexAdjustment, - llvm::Optional()); + llvm::Optional(), + /*ExpectParameterPack=*/false); } if (!NewParm) diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp index c0f9e21b35..75615ee295 100644 --- a/test/SemaTemplate/alias-templates.cpp +++ b/test/SemaTemplate/alias-templates.cpp @@ -85,7 +85,7 @@ namespace PR11848 { template struct Hidden1 { template - Hidden1(typename T::template U ...ts); + Hidden1(typename T::template U ...ts); // expected-error{{type 'typename Hide::U' (aka 'int') of function parameter pack does not contain any unexpanded parameter packs}} }; template @@ -97,7 +97,6 @@ namespace PR11848 { template using U = int; }; - // FIXME: This case crashes clang at the moment. - //Hidden1 h1; + Hidden1 h1; // expected-note{{in instantiation of template class 'PR11848::Hidden1' requested here}} Hidden2 h2(1, 2); } -- 2.40.0