forked from OSchip/llvm-project
Fix template argument deduction when only some of a parameter pack is a non-deduced context.
When a parameter pack has multiple corresponding arguments, and some subset of them are overloaded functions, it's possible that some subset of the parameters are non-deduced contexts. In such a case, keep deducing from the remainder of the arguments, and resolve the incomplete pack against whatever other deductions we've performed for the pack. GCC, MSVC, and ICC give three different bad behaviors for this case; what we do now (and what we did before) don't exactly match any of them, sadly :( I'm getting a core issue opened to specify more precisely how this should be handled. llvm-svn: 290923
This commit is contained in:
parent
e28ab799b2
commit
539e8e3703
|
@ -3921,6 +3921,8 @@ def ext_ms_deref_template_argument: ExtWarn<
|
|||
def ext_ms_delayed_template_argument: ExtWarn<
|
||||
"using the undeclared type %0 as a default template argument is a "
|
||||
"Microsoft extension">, InGroup<MicrosoftTemplate>;
|
||||
def err_template_arg_deduced_incomplete_pack : Error<
|
||||
"deduced incomplete pack %0 for template parameter %1">;
|
||||
|
||||
// C++ template specialization
|
||||
def err_template_spec_unknown_kind : Error<
|
||||
|
|
|
@ -288,19 +288,22 @@ checkDeducedTemplateArguments(ASTContext &Context,
|
|||
X.pack_size() != Y.pack_size())
|
||||
return DeducedTemplateArgument();
|
||||
|
||||
llvm::SmallVector<TemplateArgument, 8> NewPack;
|
||||
for (TemplateArgument::pack_iterator XA = X.pack_begin(),
|
||||
XAEnd = X.pack_end(),
|
||||
YA = Y.pack_begin();
|
||||
XA != XAEnd; ++XA, ++YA) {
|
||||
// FIXME: Do we need to merge the results together here?
|
||||
if (checkDeducedTemplateArguments(Context,
|
||||
DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()),
|
||||
DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound()))
|
||||
.isNull())
|
||||
TemplateArgument Merged = checkDeducedTemplateArguments(
|
||||
Context, DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()),
|
||||
DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound()));
|
||||
if (Merged.isNull())
|
||||
return DeducedTemplateArgument();
|
||||
NewPack.push_back(Merged);
|
||||
}
|
||||
|
||||
return X;
|
||||
return DeducedTemplateArgument(
|
||||
TemplateArgument::CreatePackCopy(Context, NewPack),
|
||||
X.wasDeducedFromArrayBound() && Y.wasDeducedFromArrayBound());
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid TemplateArgument Kind!");
|
||||
|
@ -672,17 +675,20 @@ public:
|
|||
// for that pack, then clear out the deduced argument.
|
||||
for (auto &Pack : Packs) {
|
||||
DeducedTemplateArgument &DeducedArg = Deduced[Pack.Index];
|
||||
if (!DeducedArg.isNull()) {
|
||||
if (!Pack.New.empty() || !DeducedArg.isNull()) {
|
||||
while (Pack.New.size() < PackElements)
|
||||
Pack.New.push_back(DeducedTemplateArgument());
|
||||
Pack.New.push_back(DeducedArg);
|
||||
DeducedArg = DeducedTemplateArgument();
|
||||
}
|
||||
}
|
||||
++PackElements;
|
||||
}
|
||||
|
||||
/// \brief Finish template argument deduction for a set of argument packs,
|
||||
/// producing the argument packs and checking for consistency with prior
|
||||
/// deductions.
|
||||
Sema::TemplateDeductionResult finish(bool HasAnyArguments) {
|
||||
Sema::TemplateDeductionResult finish() {
|
||||
// Build argument packs for each of the parameter packs expanded by this
|
||||
// pack expansion.
|
||||
for (auto &Pack : Packs) {
|
||||
|
@ -691,7 +697,7 @@ public:
|
|||
|
||||
// Build or find a new value for this pack.
|
||||
DeducedTemplateArgument NewPack;
|
||||
if (HasAnyArguments && Pack.New.empty()) {
|
||||
if (PackElements && Pack.New.empty()) {
|
||||
if (Pack.DeferredDeduction.isNull()) {
|
||||
// We were not able to deduce anything for this parameter pack
|
||||
// (because it only appeared in non-deduced contexts), so just
|
||||
|
@ -758,6 +764,7 @@ private:
|
|||
TemplateParameterList *TemplateParams;
|
||||
SmallVectorImpl<DeducedTemplateArgument> &Deduced;
|
||||
TemplateDeductionInfo &Info;
|
||||
unsigned PackElements = 0;
|
||||
|
||||
SmallVector<DeducedPack, 2> Packs;
|
||||
};
|
||||
|
@ -861,10 +868,7 @@ DeduceTemplateArguments(Sema &S,
|
|||
QualType Pattern = Expansion->getPattern();
|
||||
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
|
||||
|
||||
bool HasAnyArguments = false;
|
||||
for (; ArgIdx < NumArgs; ++ArgIdx) {
|
||||
HasAnyArguments = true;
|
||||
|
||||
// Deduce template arguments from the pattern.
|
||||
if (Sema::TemplateDeductionResult Result
|
||||
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
|
||||
|
@ -877,7 +881,7 @@ DeduceTemplateArguments(Sema &S,
|
|||
|
||||
// Build argument packs for each of the parameter packs expanded by this
|
||||
// pack expansion.
|
||||
if (auto Result = PackScope.finish(HasAnyArguments))
|
||||
if (auto Result = PackScope.finish())
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -1935,10 +1939,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
|
|||
// Keep track of the deduced template arguments for each parameter pack
|
||||
// expanded by this pack expansion (the outer index) and for each
|
||||
// template argument (the inner SmallVectors).
|
||||
bool HasAnyArguments = false;
|
||||
for (; hasTemplateArgumentForDeduction(Args, ArgIdx); ++ArgIdx) {
|
||||
HasAnyArguments = true;
|
||||
|
||||
// Deduce template arguments from the pattern.
|
||||
if (Sema::TemplateDeductionResult Result
|
||||
= DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
|
||||
|
@ -1950,7 +1951,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
|
|||
|
||||
// Build argument packs for each of the parameter packs expanded by this
|
||||
// pack expansion.
|
||||
if (auto Result = PackScope.finish(HasAnyArguments))
|
||||
if (auto Result = PackScope.finish())
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -2145,6 +2146,16 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
|
|||
InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
|
||||
assert(InnerArg.getKind() != TemplateArgument::Pack &&
|
||||
"deduced nested pack");
|
||||
if (P.isNull()) {
|
||||
// We deduced arguments for some elements of this pack, but not for
|
||||
// all of them. This happens if we get a conditionally-non-deduced
|
||||
// context in a pack expansion (such as an overload set in one of the
|
||||
// arguments).
|
||||
S.Diag(Param->getLocation(),
|
||||
diag::err_template_arg_deduced_incomplete_pack)
|
||||
<< Arg << Param;
|
||||
return true;
|
||||
}
|
||||
if (ConvertArg(InnerArg, PackedArgsBuilder.size()))
|
||||
return true;
|
||||
|
||||
|
@ -3436,10 +3447,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
|||
PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info,
|
||||
ParamPattern);
|
||||
|
||||
bool HasAnyArguments = false;
|
||||
for (; ArgIdx < Args.size(); ++ArgIdx) {
|
||||
HasAnyArguments = true;
|
||||
|
||||
for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) {
|
||||
QualType OrigParamType = ParamPattern;
|
||||
ParamType = OrigParamType;
|
||||
Expr *Arg = Args[ArgIdx];
|
||||
|
@ -3448,18 +3456,21 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
|||
unsigned TDF = 0;
|
||||
if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
|
||||
ParamType, ArgType, Arg,
|
||||
TDF)) {
|
||||
// We can't actually perform any deduction for this argument, so stop
|
||||
// deduction at this point.
|
||||
++ArgIdx;
|
||||
break;
|
||||
}
|
||||
TDF))
|
||||
continue;
|
||||
|
||||
// Keep track of the argument type and corresponding argument index,
|
||||
// so we can check for compatibility between the deduced A and A.
|
||||
if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
|
||||
continue;
|
||||
|
||||
// As above, initializer lists need special handling.
|
||||
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
|
||||
TemplateDeductionResult Result;
|
||||
if (!DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE,
|
||||
Info, Deduced, TDF, Result)) {
|
||||
// FIXME: Bailing out here is wrong; we could still need to deduce
|
||||
// from later pack elements.
|
||||
++ArgIdx;
|
||||
break;
|
||||
}
|
||||
|
@ -3467,12 +3478,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
|||
if (Result)
|
||||
return Result;
|
||||
} else {
|
||||
|
||||
// Keep track of the argument type and corresponding argument index,
|
||||
// so we can check for compatibility between the deduced A and A.
|
||||
if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
|
||||
OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
|
||||
ArgType));
|
||||
OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
|
||||
ArgType));
|
||||
|
||||
if (TemplateDeductionResult Result
|
||||
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
|
||||
|
@ -3480,13 +3487,11 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
|||
Deduced, TDF))
|
||||
return Result;
|
||||
}
|
||||
|
||||
PackScope.nextPackElement();
|
||||
}
|
||||
|
||||
// Build argument packs for each of the parameter packs expanded by this
|
||||
// pack expansion.
|
||||
if (auto Result = PackScope.finish(HasAnyArguments))
|
||||
if (auto Result = PackScope.finish())
|
||||
return Result;
|
||||
|
||||
// After we've matching against a parameter pack, we're done.
|
||||
|
|
|
@ -362,3 +362,41 @@ namespace deduction_after_explicit_pack {
|
|||
g<int, float&, double&>(a, b, c, &c); // ok
|
||||
}
|
||||
}
|
||||
|
||||
namespace overload_vs_pack {
|
||||
void f(int);
|
||||
void f(float);
|
||||
void g(double);
|
||||
|
||||
template<typename ...T> struct X {};
|
||||
template<typename ...T> void x(T...);
|
||||
|
||||
template<typename ...T> struct Y { typedef int type(typename T::error...); };
|
||||
template<> struct Y<int, float, double> { typedef int type; };
|
||||
|
||||
template<typename ...T> typename Y<T...>::type g1(X<T...>, void (*...fns)(T)); // expected-note {{deduced conflicting types for parameter 'T' (<int, float> vs. <(no value), double>)}}
|
||||
template<typename ...T> typename Y<T...>::type g2(void(*)(T...), void (*...fns)(T)); // expected-note {{deduced conflicting types for parameter 'T' (<int, float> vs. <(no value), double>)}}
|
||||
|
||||
template<typename T> int &h1(decltype(g1(X<int, float, T>(), f, f, g)) *p);
|
||||
template<typename T> float &h1(...);
|
||||
|
||||
template<typename T> int &h2(decltype(g2(x<int, float, T>, f, f, g)) *p);
|
||||
template<typename T> float &h2(...);
|
||||
|
||||
int n1 = g1(X<int, float>(), f, g); // expected-error {{no matching function}}
|
||||
int n2 = g2(x<int, float>, f, g); // expected-error {{no matching function}}
|
||||
int n3 = g1(X<int, float, double, char>(), f);
|
||||
int n4 = g2(x<int, float, double, long>, f);
|
||||
|
||||
int &a1 = h1<double>(0); // ok, skip deduction for 'f's, deduce matching value from 'g'
|
||||
int &a2 = h2<double>(0);
|
||||
|
||||
float &b1 = h1<float>(0); // deduce mismatching value from 'g', so we do not trigger instantiation of Y
|
||||
float &b2 = h2<float>(0);
|
||||
|
||||
template<typename ...T> int partial_deduction(void (*...f)(T)); // expected-note {{deduced incomplete pack <(no value), double> for template parameter 'T'}}
|
||||
int pd1 = partial_deduction(f, g); // expected-error {{no matching function}}
|
||||
|
||||
template<typename ...T> int partial_deduction_2(void (*...f)(T), ...); // expected-note {{deduced incomplete pack <(no value), double> for template parameter 'T'}}
|
||||
int pd2 = partial_deduction_2(f, g); // expected-error {{no matching function}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue