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.

llvm-svn: 148960
This commit is contained in:
Douglas Gregor 2012-01-25 16:15:54 +00:00
parent f7bf3db070
commit 0dd22bc4d6
5 changed files with 37 additions and 19 deletions

View File

@ -5100,7 +5100,8 @@ public:
ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,
llvm::Optional<unsigned> NumExpansions);
llvm::Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
bool SubstParmTypes(SourceLocation Loc,
ParmVarDecl **Params, unsigned NumParams,
const MultiLevelTemplateArgumentList &TemplateArgs,

View File

@ -778,7 +778,8 @@ namespace {
FunctionProtoTypeLoc TL);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
llvm::Optional<unsigned> NumExpansions);
llvm::Optional<unsigned> 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<unsigned> NumExpansions) {
llvm::Optional<unsigned> 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<unsigned> NumExpansions) {
llvm::Optional<unsigned> 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);

View File

@ -1601,7 +1601,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0,
llvm::Optional<unsigned>());
llvm::Optional<unsigned>(),
/*ExpectParameterPack=*/false);
}
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(

View File

@ -530,7 +530,8 @@ public:
/// scope index; can be negative
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
llvm::Optional<unsigned> NumExpansions);
llvm::Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
@ -3814,12 +3815,14 @@ template<typename Derived>
ParmVarDecl *
TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
llvm::Optional<unsigned> NumExpansions) {
llvm::Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
TypeSourceInfo *NewDI = 0;
if (NumExpansions && isa<PackExpansionType>(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<PackExpansionTypeLoc>(OldTL);
@ -3916,7 +3919,8 @@ bool TreeTransform<Derived>::
ParmVarDecl *NewParm
= getDerived().TransformFunctionTypeParam(OldParm,
indexAdjustment++,
OrigNumExpansions);
OrigNumExpansions,
/*ExpectParameterPack=*/false);
if (!NewParm)
return true;
@ -3932,7 +3936,8 @@ bool TreeTransform<Derived>::
ParmVarDecl *NewParm
= getDerived().TransformFunctionTypeParam(OldParm,
indexAdjustment++,
OrigNumExpansions);
OrigNumExpansions,
/*ExpectParameterPack=*/false);
if (!NewParm)
return true;
@ -3956,11 +3961,13 @@ bool TreeTransform<Derived>::
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
NewParm = getDerived().TransformFunctionTypeParam(OldParm,
indexAdjustment,
NumExpansions);
NumExpansions,
/*ExpectParameterPack=*/true);
} else {
NewParm = getDerived().TransformFunctionTypeParam(OldParm,
indexAdjustment,
llvm::Optional<unsigned>());
llvm::Optional<unsigned>(),
/*ExpectParameterPack=*/false);
}
if (!NewParm)

View File

@ -85,7 +85,7 @@ namespace PR11848 {
template<typename T>
struct Hidden1 {
template<typename ...Ts>
Hidden1(typename T::template U<Ts> ...ts);
Hidden1(typename T::template U<Ts> ...ts); // expected-error{{type 'typename Hide::U<Ts>' (aka 'int') of function parameter pack does not contain any unexpanded parameter packs}}
};
template<typename T, typename ...Ts>
@ -97,7 +97,6 @@ namespace PR11848 {
template<typename T> using U = int;
};
// FIXME: This case crashes clang at the moment.
//Hidden1<Hide> h1;
Hidden1<Hide> h1; // expected-note{{in instantiation of template class 'PR11848::Hidden1<PR11848::Hide>' requested here}}
Hidden2<Hide, double, char> h2(1, 2);
}