aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-14 17:04:44 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-14 17:04:44 +0000
commitcded4f649cd4b7ba7d461c25c6482ef52b8d3a2a (patch)
tree886197b026701bb900caeca77c4135297c4b276a /lib/Sema
parent5576d9b0a389f6f1f89bdcd37194f4e992b1fbcb (diff)
Keep track of the number of expansions to be produced from a type pack
expansion, when it is known due to the substitution of an out parameter pack. This allows us to properly handle substitution into pack expansions that involve multiple parameter packs at different template parameter levels, even when this substitution happens one level at a time (as with partial specializations of member class templates and the signatures of member function templates). Note that the diagnostic we provide when there is an arity mismatch between an outer parameter pack and an inner parameter pack in this case isn't as clear as the normal diagnostic for an arity mismatch. However, this doesn't matter because these cases are very, very rare and (even then) only typically occur in a SFINAE context. The other kinds of pack expansions (expression, template, etc.) still need to support optional tracking of the number of expansions, and we need the moral equivalent of SubstTemplateTypeParmPackType for substituted argument packs of template template and non-type template parameters. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123448 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp10
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp13
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp30
-rw-r--r--lib/Sema/SemaType.cpp4
-rw-r--r--lib/Sema/TreeTransform.h63
5 files changed, 75 insertions, 45 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 629dc58958..c181a568b5 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -622,7 +622,7 @@ namespace {
unsigned NumUnexpanded,
bool &ShouldExpand,
bool &RetainExpansion,
- unsigned &NumExpansions) {
+ llvm::Optional<unsigned> &NumExpansions) {
return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
PatternRange, Unexpanded,
NumUnexpanded,
@@ -1260,7 +1260,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
// We still have unexpanded parameter packs, which means that
// our function parameter is still a function parameter pack.
// Therefore, make its type a pack expansion type.
- NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc());
+ // FIXME: Variadic templates num expansions.
+ NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(),
+ llvm::Optional<unsigned>());
}
} else {
NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
@@ -1360,7 +1362,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
- unsigned NumExpansions = 0;
+ llvm::Optional<unsigned> NumExpansions;
if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(),
Base->getSourceRange(),
Unexpanded.data(), Unexpanded.size(),
@@ -1373,7 +1375,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
// If we should expand this pack expansion now, do so.
if (ShouldExpand) {
- for (unsigned I = 0; I != NumExpansions; ++I) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a18bfbafc0..6b5713a2fa 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1977,7 +1977,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
bool Expand = false;
bool RetainExpansion = false;
- unsigned NumExpansions = 0;
+ llvm::Optional<unsigned> NumExpansions
+ = PackExpansion->getNumExpansions();
if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
SourceRange(),
Unexpanded.data(),
@@ -1990,7 +1991,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
if (!Expand) {
// We can't expand this pack expansion into separate arguments yet;
- // just substitute into the argument pack.
+ // just substitute into the pattern and create a new pack expansion
+ // type.
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
TemplateArgs,
@@ -1998,13 +2000,14 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
if (T.isNull())
break;
+ T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
Exceptions.push_back(T);
continue;
}
// Substitute into the pack expansion pattern for each template
bool Invalid = false;
- for (unsigned ArgIdx = 0; ArgIdx != NumExpansions; ++ArgIdx) {
+ for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
@@ -2384,7 +2387,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
collectUnexpandedParameterPacks(BaseTL, Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
- unsigned NumExpansions = 0;
+ llvm::Optional<unsigned> NumExpansions;
if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(),
BaseTL.getSourceRange(),
Unexpanded.data(),
@@ -2399,7 +2402,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
assert(ShouldExpand && "Partial instantiation of base initializer?");
// Loop over all of the arguments in the argument pack(s),
- for (unsigned I = 0; I != NumExpansions; ++I) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
// Instantiate the initializer.
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index dc5013c25d..899b58e558 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -368,7 +368,8 @@ TypeResult Sema::ActOnPackExpansion(ParsedType Type,
if (!TSInfo)
return true;
- TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc);
+ TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc,
+ llvm::Optional<unsigned>());
if (!TSResult)
return true;
@@ -376,11 +377,12 @@ TypeResult Sema::ActOnPackExpansion(ParsedType Type,
}
TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
- SourceLocation EllipsisLoc) {
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
// Create the pack expansion type and source-location information.
QualType Result = CheckPackExpansion(Pattern->getType(),
Pattern->getTypeLoc().getSourceRange(),
- EllipsisLoc);
+ EllipsisLoc, NumExpansions);
if (Result.isNull())
return 0;
@@ -397,7 +399,8 @@ TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
QualType Sema::CheckPackExpansion(QualType Pattern,
SourceRange PatternRange,
- SourceLocation EllipsisLoc) {
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
// C++0x [temp.variadic]p5:
// The pattern of a pack expansion shall name one or more
// parameter packs that are not expanded by a nested pack
@@ -408,7 +411,7 @@ QualType Sema::CheckPackExpansion(QualType Pattern,
return QualType();
}
- return Context.getPackExpansionType(Pattern);
+ return Context.getPackExpansionType(Pattern, NumExpansions);
}
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
@@ -450,7 +453,7 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool &ShouldExpand,
bool &RetainExpansion,
- unsigned &NumExpansions) {
+ llvm::Optional<unsigned> &NumExpansions) {
ShouldExpand = true;
RetainExpansion = false;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
@@ -527,7 +530,7 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
RetainExpansion = true;
}
- if (!HaveFirstPack) {
+ if (!NumExpansions) {
// The is the first pack we've seen for which we have an argument.
// Record it.
NumExpansions = NewPackSize;
@@ -537,13 +540,18 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
continue;
}
- if (NewPackSize != NumExpansions) {
+ if (NewPackSize != *NumExpansions) {
// C++0x [temp.variadic]p5:
// All of the parameter packs expanded by a pack expansion shall have
// the same number of arguments specified.
- Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
- << FirstPack.first << Name << NumExpansions << NewPackSize
- << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
+ if (HaveFirstPack)
+ Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
+ << FirstPack.first << Name << *NumExpansions << NewPackSize
+ << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
+ else
+ Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
+ << Name << *NumExpansions << NewPackSize
+ << SourceRange(Unexpanded[I].second);
return true;
}
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index ada8a1d8a2..e843ca5fca 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1927,7 +1927,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
<< T << D.getSourceRange();
D.setEllipsisLoc(SourceLocation());
} else {
- T = Context.getPackExpansionType(T);
+ T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
}
break;
@@ -1941,7 +1941,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// parameter packs in the type of the non-type template parameter, then
// it expands those parameter packs.
if (T->containsUnexpandedParameterPack())
- T = Context.getPackExpansionType(T);
+ T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
else if (!getLangOptions().CPlusPlus0x)
Diag(D.getEllipsisLoc(), diag::err_variadic_templates);
break;
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 4127d5045a..f2496c2f1a 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -227,8 +227,12 @@ public:
/// C++0x [temp.arg.explicit]p9.
///
/// \param NumExpansions The number of separate arguments that will be in
- /// the expanded form of the corresponding pack expansion. Must be set when
- /// \c ShouldExpand is \c true.
+ /// the expanded form of the corresponding pack expansion. This is both an
+ /// input and an output parameter, which can be set by the caller if the
+ /// number of expansions is known a priori (e.g., due to a prior substitution)
+ /// and will be set by the callee when the number of expansions is known.
+ /// The callee must set this value when \c ShouldExpand is \c true; it may
+ /// set this value in other cases.
///
/// \returns true if an error occurred (e.g., because the parameter packs
/// are to be instantiated with arguments of different lengths), false
@@ -240,7 +244,7 @@ public:
unsigned NumUnexpanded,
bool &ShouldExpand,
bool &RetainExpansion,
- unsigned &NumExpansions) {
+ llvm::Optional<unsigned> &NumExpansions) {
ShouldExpand = false;
return false;
}
@@ -814,8 +818,10 @@ public:
/// Subclasses may override this routine to provide different behavior.
QualType RebuildPackExpansionType(QualType Pattern,
SourceRange PatternRange,
- SourceLocation EllipsisLoc) {
- return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc);
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
+ return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc,
+ NumExpansions);
}
/// \brief Build a new nested-name-specifier given the prefix and an
@@ -2165,7 +2171,8 @@ public:
/// for a template argument. Subclasses may override this routine to provide
/// different behavior.
TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
- SourceLocation EllipsisLoc) {
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
switch (Pattern.getArgument().getKind()) {
case TemplateArgument::Expression: {
ExprResult Result
@@ -2195,7 +2202,8 @@ public:
case TemplateArgument::Type:
if (TypeSourceInfo *Expansion
= getSema().CheckPackExpansion(Pattern.getTypeSourceInfo(),
- EllipsisLoc))
+ EllipsisLoc,
+ NumExpansions))
return TemplateArgumentLoc(TemplateArgument(Expansion->getType()),
Expansion);
break;
@@ -2300,7 +2308,7 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
- unsigned NumExpansions = 0;
+ llvm::Optional<unsigned> NumExpansions;
if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(),
Pattern->getSourceRange(),
Unexpanded.data(),
@@ -2318,6 +2326,7 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
if (OutPattern.isInvalid())
return true;
+ // FIXME: Variadic templates NumExpansions
ExprResult Out = getDerived().RebuildPackExpansion(OutPattern.get(),
Expansion->getEllipsisLoc());
if (Out.isInvalid())
@@ -2331,7 +2340,7 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
// The transform has determined that we should perform an elementwise
// expansion of the pattern. Do so.
- for (unsigned I = 0; I != NumExpansions; ++I) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
ExprResult Out = getDerived().TransformExpr(Pattern);
if (Out.isInvalid())
@@ -2817,8 +2826,10 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
// We have a pack expansion, for which we will be substituting into
// the pattern.
SourceLocation Ellipsis;
+ llvm::Optional<unsigned> OrigNumExpansions;
TemplateArgumentLoc Pattern
- = In.getPackExpansionPattern(Ellipsis, getSema().Context);
+ = In.getPackExpansionPattern(Ellipsis, OrigNumExpansions,
+ getSema().Context);
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
@@ -2828,7 +2839,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
- unsigned NumExpansions = 0;
+ llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(Ellipsis,
Pattern.getSourceRange(),
Unexpanded.data(),
@@ -2847,7 +2858,8 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
if (getDerived().TransformTemplateArgument(Pattern, OutPattern))
return true;
- Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis);
+ Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis,
+ NumExpansions);
if (Out.getArgument().isNull())
return true;
@@ -2857,14 +2869,15 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
// The transform has determined that we should perform an elementwise
// expansion of the pattern. Do so.
- for (unsigned I = 0; I != NumExpansions; ++I) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
if (getDerived().TransformTemplateArgument(Pattern, Out))
return true;
if (Out.getArgument().containsUnexpandedParameterPack()) {
- Out = getDerived().RebuildPackExpansion(Out, Ellipsis);
+ Out = getDerived().RebuildPackExpansion(Out, Ellipsis,
+ OrigNumExpansions);
if (Out.getArgument().isNull())
return true;
}
@@ -2880,7 +2893,8 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
if (getDerived().TransformTemplateArgument(Pattern, Out))
return true;
- Out = getDerived().RebuildPackExpansion(Out, Ellipsis);
+ Out = getDerived().RebuildPackExpansion(Out, Ellipsis,
+ OrigNumExpansions);
if (Out.getArgument().isNull())
return true;
@@ -3497,7 +3511,7 @@ bool TreeTransform<Derived>::
// Determine whether we should expand the parameter packs.
bool ShouldExpand = false;
bool RetainExpansion = false;
- unsigned NumExpansions = 0;
+ llvm::Optional<unsigned> NumExpansions;
if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
Pattern.getSourceRange(),
Unexpanded.data(),
@@ -3512,7 +3526,7 @@ bool TreeTransform<Derived>::
// Expand the function parameter pack into multiple, separate
// parameters.
getDerived().ExpandingFunctionParameterPack(OldParm);
- for (unsigned I = 0; I != NumExpansions; ++I) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
ParmVarDecl *NewParm
= getDerived().TransformFunctionTypeParam(OldParm);
@@ -3546,6 +3560,7 @@ bool TreeTransform<Derived>::
// expansion.
}
+ // FIXME: Variadic templates num expansions
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm);
if (!NewParm)
@@ -3561,6 +3576,7 @@ bool TreeTransform<Derived>::
// declaration for this parameter.
QualType OldType = ParamTypes[i];
bool IsPackExpansion = false;
+ llvm::Optional<unsigned> NumExpansions;
if (const PackExpansionType *Expansion
= dyn_cast<PackExpansionType>(OldType)) {
// We have a function parameter pack that may need to be expanded.
@@ -3571,7 +3587,6 @@ bool TreeTransform<Derived>::
// Determine whether we should expand the parameter packs.
bool ShouldExpand = false;
bool RetainExpansion = false;
- unsigned NumExpansions = 0;
if (getDerived().TryExpandParameterPacks(Loc, SourceRange(),
Unexpanded.data(),
Unexpanded.size(),
@@ -3584,7 +3599,7 @@ bool TreeTransform<Derived>::
if (ShouldExpand) {
// Expand the function parameter pack into multiple, separate
// parameters.
- for (unsigned I = 0; I != NumExpansions; ++I) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
QualType NewType = getDerived().TransformType(Pattern);
if (NewType.isNull())
@@ -3624,7 +3639,8 @@ bool TreeTransform<Derived>::
return true;
if (IsPackExpansion)
- NewType = getSema().Context.getPackExpansionType(NewType);
+ NewType = getSema().Context.getPackExpansionType(NewType,
+ NumExpansions);
OutParamTypes.push_back(NewType);
if (PVars)
@@ -4259,7 +4275,8 @@ QualType TreeTransform<Derived>::TransformPackExpansionType(TypeLocBuilder &TLB,
Pattern != TL.getPatternLoc().getType()) {
Result = getDerived().RebuildPackExpansionType(Pattern,
TL.getPatternLoc().getSourceRange(),
- TL.getEllipsisLoc());
+ TL.getEllipsisLoc(),
+ TL.getTypePtr()->getNumExpansions());
if (Result.isNull())
return QualType();
}
@@ -6818,7 +6835,7 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
bool ShouldExpand = false;
bool RetainExpansion = false;
- unsigned NumExpansions = 0;
+ llvm::Optional<unsigned> NumExpansions;
if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(),
&Unexpanded, 1,
ShouldExpand, RetainExpansion,
@@ -6832,7 +6849,7 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
// that stores that length.
return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(),
E->getPackLoc(), E->getRParenLoc(),
- NumExpansions);
+ *NumExpansions);
}
template<typename Derived>