forked from OSchip/llvm-project
Implement partial ordering of class template partial specializations
and function templates that contain variadic templates. This involves three small-ish changes: (1) When transforming a pack expansion, if the transformed argument still contains unexpanded parameter packs, build a pack expansion. This can happen during the substitution that occurs into class template partial specialiation template arguments during partial ordering. (2) When performing template argument deduction where the argument is a pack expansion, match against the pattern of that pack expansion. (3) When performing template argument deduction against a non-pack parameter, or a non-expansion template argument, deduction fails if the argument itself is a pack expansion (C++0x [temp.deduct.type]p22). llvm-svn: 123279
This commit is contained in:
parent
cb9c4f85ec
commit
2fcb863b2b
|
@ -80,7 +80,7 @@ static Sema::TemplateDeductionResult
|
|||
DeduceTemplateArguments(Sema &S,
|
||||
TemplateParameterList *TemplateParams,
|
||||
const TemplateArgument &Param,
|
||||
const TemplateArgument &Arg,
|
||||
TemplateArgument Arg,
|
||||
TemplateDeductionInfo &Info,
|
||||
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced);
|
||||
|
||||
|
@ -677,6 +677,13 @@ DeduceTemplateArguments(Sema &S,
|
|||
if (ArgIdx >= NumArgs)
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
|
||||
if (isa<PackExpansionType>(Args[ArgIdx])) {
|
||||
// C++0x [temp.deduct.type]p22:
|
||||
// If the original function parameter associated with A is a function
|
||||
// parameter pack and the function parameter associated with P is not
|
||||
// a function parameter pack, then template argument deduction fails.
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
}
|
||||
|
||||
if (Sema::TemplateDeductionResult Result
|
||||
= DeduceTemplateArguments(S, TemplateParams,
|
||||
|
@ -814,6 +821,12 @@ DeduceTemplateArguments(Sema &S,
|
|||
QualType Param = S.Context.getCanonicalType(ParamIn);
|
||||
QualType Arg = S.Context.getCanonicalType(ArgIn);
|
||||
|
||||
// If the argument type is a pack expansion, look at its pattern.
|
||||
// This isn't explicitly called out
|
||||
if (const PackExpansionType *ArgExpansion
|
||||
= dyn_cast<PackExpansionType>(Arg))
|
||||
Arg = ArgExpansion->getPattern();
|
||||
|
||||
if (PartialOrdering) {
|
||||
// C++0x [temp.deduct.partial]p5:
|
||||
// Before the partial ordering is done, certain transformations are
|
||||
|
@ -1273,9 +1286,15 @@ static Sema::TemplateDeductionResult
|
|||
DeduceTemplateArguments(Sema &S,
|
||||
TemplateParameterList *TemplateParams,
|
||||
const TemplateArgument &Param,
|
||||
const TemplateArgument &Arg,
|
||||
TemplateArgument Arg,
|
||||
TemplateDeductionInfo &Info,
|
||||
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
|
||||
// If the template argument is a pack expansion, perform template argument
|
||||
// deduction against the pattern of that expansion. This only occurs during
|
||||
// partial ordering.
|
||||
if (Arg.isPackExpansion())
|
||||
Arg = Arg.getPackExpansionPattern();
|
||||
|
||||
switch (Param.getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
assert(false && "Null template argument in parameter list");
|
||||
|
@ -1448,11 +1467,17 @@ DeduceTemplateArguments(Sema &S,
|
|||
return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch
|
||||
: Sema::TDK_Success;
|
||||
|
||||
if (Args[ArgIdx].isPackExpansion()) {
|
||||
// FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,
|
||||
// but applied to pack expansions that are template arguments.
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
}
|
||||
|
||||
// Perform deduction for this Pi/Ai pair.
|
||||
if (Sema::TemplateDeductionResult Result
|
||||
= DeduceTemplateArguments(S, TemplateParams,
|
||||
Params[ParamIdx], Args[ArgIdx],
|
||||
Info, Deduced))
|
||||
= DeduceTemplateArguments(S, TemplateParams,
|
||||
Params[ParamIdx], Args[ArgIdx],
|
||||
Info, Deduced))
|
||||
return Result;
|
||||
|
||||
// Move to the next argument.
|
||||
|
@ -1792,7 +1817,7 @@ FinishTemplateArgumentDeduction(Sema &S,
|
|||
return Sema::TDK_SubstitutionFailure;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Form the template argument list from the deduced template arguments.
|
||||
TemplateArgumentList *DeducedArgumentList
|
||||
= TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
|
||||
|
|
|
@ -2327,6 +2327,12 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
|
|||
if (Out.isInvalid())
|
||||
return true;
|
||||
|
||||
if (Out.get()->containsUnexpandedParameterPack()) {
|
||||
Out = RebuildPackExpansion(Out.get(), Expansion->getEllipsisLoc());
|
||||
if (Out.isInvalid())
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ArgChanged)
|
||||
*ArgChanged = true;
|
||||
Outputs.push_back(Out.get());
|
||||
|
@ -2847,6 +2853,12 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
|
|||
if (getDerived().TransformTemplateArgument(Pattern, Out))
|
||||
return true;
|
||||
|
||||
if (Out.getArgument().containsUnexpandedParameterPack()) {
|
||||
Out = getDerived().RebuildPackExpansion(Out, Ellipsis);
|
||||
if (Out.getArgument().isNull())
|
||||
return true;
|
||||
}
|
||||
|
||||
Outputs.addArgument(Out);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||
|
||||
// Various tests related to partial ordering of variadic templates.
|
||||
template<typename ...Types> struct tuple;
|
||||
|
||||
template<typename Tuple>
|
||||
struct X1 {
|
||||
static const unsigned value = 0;
|
||||
};
|
||||
|
||||
template<typename Head, typename ...Tail>
|
||||
struct X1<tuple<Head, Tail...> > {
|
||||
static const unsigned value = 1;
|
||||
};
|
||||
|
||||
template<typename Head, typename ...Tail>
|
||||
struct X1<tuple<Head, Tail&...> > {
|
||||
static const unsigned value = 2;
|
||||
};
|
||||
|
||||
template<typename Head, typename ...Tail>
|
||||
struct X1<tuple<Head&, Tail&...> > {
|
||||
static const unsigned value = 3;
|
||||
};
|
||||
|
||||
int check0[X1<tuple<>>::value == 0? 1 : -1];
|
||||
int check1[X1<tuple<int>>::value == 2? 1 : -1];
|
||||
int check2[X1<tuple<int, int>>::value == 1? 1 : -1];
|
||||
int check3[X1<tuple<int, int&>>::value == 2? 1 : -1];
|
||||
int check4[X1<tuple<int&, int&>>::value == 3? 1 : -1];
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||
|
||||
// Note: Partial ordering of function templates containing template
|
||||
// parameter packs is independent of the number of deduced arguments
|
||||
// for those template parameter packs.
|
||||
template<class ...> struct Tuple { };
|
||||
template<class ... Types> int &g(Tuple<Types ...>); // #1
|
||||
template<class T1, class ... Types> float &g(Tuple<T1, Types ...>); // #2
|
||||
template<class T1, class ... Types> double &g(Tuple<T1, Types& ...>); // #3
|
||||
|
||||
void test_g() {
|
||||
int &ir1 = g(Tuple<>());
|
||||
float &fr1 = g(Tuple<int, float>());
|
||||
double &dr1 = g(Tuple<int, float&>());
|
||||
double &dr2 = g(Tuple<int>());
|
||||
}
|
||||
|
||||
template<class ... Types> int &h(int (*)(Types ...)); // #1
|
||||
template<class T1, class ... Types> float &h(int (*)(T1, Types ...)); // #2
|
||||
template<class T1, class ... Types> double &h(int (*)(T1, Types& ...)); // #3
|
||||
|
||||
void test_h() {
|
||||
int &ir1 = h((int(*)())0);
|
||||
float &fr1 = h((int(*)(int, float))0);
|
||||
double &dr1 = h((int(*)(int, float&))0);
|
||||
double &dr2 = h((int(*)(int))0);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||
|
||||
// If the original function parameter associated with A is a function
|
||||
// parameter pack and the function parameter associated with P is not
|
||||
// a function parameter pack, then template argument deduction fails.
|
||||
template<class ... Args> int& f(Args ... args);
|
||||
template<class T1, class ... Args> float& f(T1 a1, Args ... args);
|
||||
template<class T1, class T2> double& f(T1 a1, T2 a2);
|
||||
|
||||
void test_f() {
|
||||
int &ir1 = f();
|
||||
float &fr1 = f(1, 2, 3);
|
||||
double &dr1 = f(1, 2);
|
||||
}
|
Loading…
Reference in New Issue