PR19878: If a pack expansion appears within another pack expansion, correctly

deduce any packs that are expanded by both expansions.

llvm-svn: 209786
This commit is contained in:
Richard Smith 2014-05-29 01:12:14 +00:00
parent 2de60eb213
commit 0a80d572b1
3 changed files with 208 additions and 203 deletions

View File

@ -19,6 +19,7 @@
namespace clang {
struct DeducedPack;
class TemplateArgumentList;
class Sema;
@ -162,6 +163,11 @@ public:
/// an overloaded function which could not be resolved to a specific
/// function.
Expr *Expression;
/// \brief Information on packs that we're currently expanding.
///
/// FIXME: This should be kept internal to SemaTemplateDeduction.
SmallVector<DeducedPack *, 8> PendingDeducedPacks;
};
} // end namespace sema

View File

@ -297,6 +297,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
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()))
@ -581,96 +582,181 @@ static TemplateParameter makeTemplateParameter(Decl *D) {
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
typedef SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
NewlyDeducedPacksType;
/// A pack that we're currently deducing.
struct clang::DeducedPack {
DeducedPack(unsigned Index) : Index(Index), Outer(nullptr) {}
/// \brief Prepare to perform template argument deduction for all of the
/// arguments in a set of argument packs.
static void
PrepareArgumentPackDeduction(Sema &S,
// The index of the pack.
unsigned Index;
// The old value of the pack before we started deducing it.
DeducedTemplateArgument Saved;
// A deferred value of this pack from an inner deduction, that couldn't be
// deduced because this deduction hadn't happened yet.
DeducedTemplateArgument DeferredDeduction;
// The new value of the pack.
SmallVector<DeducedTemplateArgument, 4> New;
// The outer deduction for this pack, if any.
DeducedPack *Outer;
};
/// A scope in which we're performing pack deduction.
class PackDeductionScope {
public:
PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
ArrayRef<unsigned> PackIndices,
SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
NewlyDeducedPacksType &NewlyDeducedPacks) {
// Save the deduced template arguments for each parameter pack expanded
TemplateDeductionInfo &Info, TemplateArgument Pattern)
: S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) {
// Compute the set of template parameter indices that correspond to
// parameter packs expanded by the pack expansion.
{
llvm::SmallBitVector SawIndices(TemplateParams->size());
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
// Save the deduced template argument for the parameter pack expanded
// by this pack expansion, then clear out the deduction.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
// Save the previously-deduced argument pack, then clear it out so that we
// can deduce a new argument pack.
SavedPacks[I] = Deduced[PackIndices[I]];
Deduced[PackIndices[I]] = TemplateArgument();
DeducedPack Pack(Index);
Pack.Saved = Deduced[Index];
Deduced[Index] = TemplateArgument();
if (!S.CurrentInstantiationScope)
continue;
Packs.push_back(Pack);
}
}
}
assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
for (auto &Pack : Packs) {
if (Info.PendingDeducedPacks.size() > Pack.Index)
Pack.Outer = Info.PendingDeducedPacks[Pack.Index];
else
Info.PendingDeducedPacks.resize(Pack.Index + 1);
Info.PendingDeducedPacks[Pack.Index] = &Pack;
if (S.CurrentInstantiationScope) {
// If the template argument pack was explicitly specified, add that to
// the set of deduced arguments.
const TemplateArgument *ExplicitArgs;
unsigned NumExplicitArgs;
if (NamedDecl *PartiallySubstitutedPack
= S.CurrentInstantiationScope->getPartiallySubstitutedPack(
&ExplicitArgs,
&NumExplicitArgs)) {
if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
NewlyDeducedPacks[I].append(ExplicitArgs,
ExplicitArgs + NumExplicitArgs);
NamedDecl *PartiallySubstitutedPack =
S.CurrentInstantiationScope->getPartiallySubstitutedPack(
&ExplicitArgs, &NumExplicitArgs);
if (PartiallySubstitutedPack &&
getDepthAndIndex(PartiallySubstitutedPack).second == Pack.Index)
Pack.New.append(ExplicitArgs, ExplicitArgs + NumExplicitArgs);
}
}
}
}
/// \brief Finish template argument deduction for a set of argument packs,
/// producing the argument packs and checking for consistency with prior
/// deductions.
static Sema::TemplateDeductionResult
FinishArgumentPackDeduction(Sema &S,
TemplateParameterList *TemplateParams,
bool HasAnyArguments,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
ArrayRef<unsigned> PackIndices,
SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
NewlyDeducedPacksType &NewlyDeducedPacks,
TemplateDeductionInfo &Info) {
~PackDeductionScope() {
for (auto &Pack : Packs)
Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
}
/// Move to deducing the next element in each pack that is being deduced.
void nextPackElement() {
// Capture the deduced template arguments for each parameter pack expanded
// by this pack expansion, add them to the list of arguments we've deduced
// for that pack, then clear out the deduced argument.
for (auto &Pack : Packs) {
DeducedTemplateArgument &DeducedArg = Deduced[Pack.Index];
if (!DeducedArg.isNull()) {
Pack.New.push_back(DeducedArg);
DeducedArg = DeducedTemplateArgument();
}
}
}
/// \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) {
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
if (HasAnyArguments && NewlyDeducedPacks[I].empty()) {
// We were not able to deduce anything for this parameter pack,
// so just restore the saved argument pack.
Deduced[PackIndices[I]] = SavedPacks[I];
for (auto &Pack : Packs) {
// Put back the old value for this pack.
Deduced[Pack.Index] = Pack.Saved;
// Build or find a new value for this pack.
DeducedTemplateArgument NewPack;
if (HasAnyArguments && 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
// restore the saved argument pack.
continue;
}
DeducedTemplateArgument NewPack;
if (NewlyDeducedPacks[I].empty()) {
NewPack = Pack.DeferredDeduction;
Pack.DeferredDeduction = TemplateArgument();
} else if (Pack.New.empty()) {
// If we deduced an empty argument pack, create it now.
NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack());
} else {
TemplateArgument *ArgumentPack
= new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()];
std::copy(NewlyDeducedPacks[I].begin(), NewlyDeducedPacks[I].end(),
ArgumentPack);
NewPack
= DeducedTemplateArgument(TemplateArgument(ArgumentPack,
NewlyDeducedPacks[I].size()),
NewlyDeducedPacks[I][0].wasDeducedFromArrayBound());
TemplateArgument *ArgumentPack =
new (S.Context) TemplateArgument[Pack.New.size()];
std::copy(Pack.New.begin(), Pack.New.end(), ArgumentPack);
NewPack = DeducedTemplateArgument(
TemplateArgument(ArgumentPack, Pack.New.size()),
Pack.New[0].wasDeducedFromArrayBound());
}
// Pick where we're going to put the merged pack.
DeducedTemplateArgument *Loc;
if (Pack.Outer) {
if (Pack.Outer->DeferredDeduction.isNull()) {
// Defer checking this pack until we have a complete pack to compare
// it against.
Pack.Outer->DeferredDeduction = NewPack;
continue;
}
Loc = &Pack.Outer->DeferredDeduction;
} else {
Loc = &Deduced[Pack.Index];
}
// Check the new pack matches any previous value.
DeducedTemplateArgument OldPack = *Loc;
DeducedTemplateArgument Result =
checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
// If we deferred a deduction of this pack, check that one now too.
if (!Result.isNull() && !Pack.DeferredDeduction.isNull()) {
OldPack = Result;
NewPack = Pack.DeferredDeduction;
Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack);
}
DeducedTemplateArgument Result
= checkDeducedTemplateArguments(S.Context, SavedPacks[I], NewPack);
if (Result.isNull()) {
Info.Param
= makeTemplateParameter(TemplateParams->getParam(PackIndices[I]));
Info.FirstArg = SavedPacks[I];
Info.Param =
makeTemplateParameter(TemplateParams->getParam(Pack.Index));
Info.FirstArg = OldPack;
Info.SecondArg = NewPack;
return Sema::TDK_Inconsistent;
}
Deduced[PackIndices[I]] = Result;
*Loc = Result;
}
return Sema::TDK_Success;
}
}
private:
Sema &S;
TemplateParameterList *TemplateParams;
SmallVectorImpl<DeducedTemplateArgument> &Deduced;
TemplateDeductionInfo &Info;
SmallVector<DeducedPack, 2> Packs;
};
/// \brief Deduce the template arguments by comparing the list of parameter
/// types to the list of argument types, as in the parameter-type-lists of
@ -773,33 +859,8 @@ DeduceTemplateArguments(Sema &S,
// comparison deduces template arguments for subsequent positions in the
// template parameter packs expanded by the function parameter pack.
// Compute the set of template parameter indices that correspond to
// parameter packs expanded by the pack expansion.
SmallVector<unsigned, 2> PackIndices;
QualType Pattern = Expansion->getPattern();
{
llvm::SmallBitVector SawIndices(TemplateParams->size());
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
}
}
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
// 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).
NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks);
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
bool HasAnyArguments = false;
for (; ArgIdx < NumArgs; ++ArgIdx) {
@ -813,24 +874,12 @@ DeduceTemplateArguments(Sema &S,
RefParamComparisons))
return Result;
// Capture the deduced template arguments for each parameter pack expanded
// by this pack expansion, add them to the list of arguments we've deduced
// for that pack, then clear out the deduced argument.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
if (!DeducedArg.isNull()) {
NewlyDeducedPacks[I].push_back(DeducedArg);
DeducedArg = DeducedTemplateArgument();
}
}
PackScope.nextPackElement();
}
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
if (Sema::TemplateDeductionResult Result
= FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks, Info))
if (auto Result = PackScope.finish(HasAnyArguments))
return Result;
}
@ -1852,41 +1901,18 @@ DeduceTemplateArguments(Sema &S,
// template parameter packs expanded by Pi.
TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
// Compute the set of template parameter indices that correspond to
// parameter packs expanded by the pack expansion.
SmallVector<unsigned, 2> PackIndices;
{
llvm::SmallBitVector SawIndices(TemplateParams->size());
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
}
}
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
// FIXME: If there are no remaining arguments, we can bail out early
// and set any deduced parameter packs to an empty argument pack.
// The latter part of this is a (minor) correctness issue.
// Save the deduced template arguments for each parameter pack expanded
// by this pack expansion, then clear out the deduction.
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks);
// Prepare to deduce the packs within the pattern.
PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern);
// 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;
while (hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) {
for (; hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs); ++ArgIdx) {
HasAnyArguments = true;
// Deduce template arguments from the pattern.
@ -1895,26 +1921,12 @@ DeduceTemplateArguments(Sema &S,
Info, Deduced))
return Result;
// Capture the deduced template arguments for each parameter pack expanded
// by this pack expansion, add them to the list of arguments we've deduced
// for that pack, then clear out the deduced argument.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
if (!DeducedArg.isNull()) {
NewlyDeducedPacks[I].push_back(DeducedArg);
DeducedArg = DeducedTemplateArgument();
}
}
++ArgIdx;
PackScope.nextPackElement();
}
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
if (Sema::TemplateDeductionResult Result
= FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks, Info))
if (auto Result = PackScope.finish(HasAnyArguments))
return Result;
}
@ -3403,30 +3415,9 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
break;
QualType ParamPattern = ParamExpansion->getPattern();
SmallVector<unsigned, 2> PackIndices;
{
llvm::SmallBitVector SawIndices(TemplateParams->size());
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
}
}
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info,
ParamPattern);
// 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).
NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks);
bool HasAnyArguments = false;
for (; ArgIdx < Args.size(); ++ArgIdx) {
HasAnyArguments = true;
@ -3476,24 +3467,12 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
return Result;
}
// Capture the deduced template arguments for each parameter pack expanded
// by this pack expansion, add them to the list of arguments we've deduced
// for that pack, then clear out the deduced argument.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
if (!DeducedArg.isNull()) {
NewlyDeducedPacks[I].push_back(DeducedArg);
DeducedArg = DeducedTemplateArgument();
}
}
PackScope.nextPackElement();
}
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
if (Sema::TemplateDeductionResult Result
= FinishArgumentPackDeduction(*this, TemplateParams, HasAnyArguments,
Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks, Info))
if (auto Result = PackScope.finish(HasAnyArguments))
return Result;
// After we've matching against a parameter pack, we're done.

View File

@ -0,0 +1,20 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
template<typename ...T> struct X {};
template<typename T, typename U> struct P {};
namespace Nested {
template<typename ...T> int f1(X<T, T...>... a); // expected-note +{{conflicting types for parameter 'T'}}
template<typename ...T> int f2(P<X<T...>, T> ...a); // expected-note +{{conflicting types for parameter 'T'}}
int a1 = f1(X<int, int, double>(), X<double, int, double>());
int a2 = f1(X<int, int>());
int a3 = f1(X<int>(), X<double>()); // expected-error {{no matching}}
int a4 = f1(X<int, int>(), X<int>()); // expected-error {{no matching}}
int a5 = f1(X<int>(), X<int, int>()); // expected-error {{no matching}}
int a6 = f1(X<int, int, int>(), X<int, int, int>(), X<int, int, int, int>()); // expected-error {{no matching}}
int b1 = f2(P<X<int, double>, int>(), P<X<int, double>, double>());
int b2 = f2(P<X<int, double>, int>(), P<X<int, double>, double>(), P<X<int, double>, char>()); // expected-error {{no matching}}
}