aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h3
-rw-r--r--include/clang/AST/TemplateBase.h4
-rw-r--r--include/clang/AST/Type.h34
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Sema/Sema.h16
-rw-r--r--lib/AST/ASTContext.cpp9
-rw-r--r--lib/AST/DeclTemplate.cpp3
-rw-r--r--lib/AST/TemplateBase.cpp4
-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
-rw-r--r--lib/Serialization/ASTReader.cpp6
-rw-r--r--lib/Serialization/ASTWriter.cpp4
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp13
16 files changed, 153 insertions, 66 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 15bc301bd9..93b793eb78 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -712,7 +712,8 @@ public:
unsigned NumArgs,
const TemplateArgument *Args) const;
- QualType getPackExpansionType(QualType Pattern);
+ QualType getPackExpansionType(QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions);
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const;
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 649c005020..93ec35bebe 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -465,7 +465,11 @@ public:
/// the pattern of the pack expansion.
///
/// \param Ellipsis Will be set to the location of the ellipsis.
+ ///
+ /// \param NumExpansions Will be set to the number of expansions that will
+ /// be generated from this pack expansion, if known a priori.
TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
+ llvm::Optional<unsigned> &NumExpansions,
ASTContext &Context) const;
};
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index c081a161de..e32676a397 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -25,6 +25,7 @@
#include "llvm/Support/type_traits.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
@@ -3379,29 +3380,52 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
/// \brief The pattern of the pack expansion.
QualType Pattern;
- PackExpansionType(QualType Pattern, QualType Canon)
+ /// \brief The number of expansions that this pack expansion will
+ /// generate when substituted (+1), or indicates that
+ ///
+ /// This field will only have a non-zero value when some of the parameter
+ /// packs that occur within the pattern have been substituted but others have
+ /// not.
+ unsigned NumExpansions;
+
+ PackExpansionType(QualType Pattern, QualType Canon,
+ llvm::Optional<unsigned> NumExpansions)
: Type(PackExpansion, Canon, /*Dependent=*/true,
/*VariableModified=*/Pattern->isVariablyModifiedType(),
/*ContainsUnexpandedParameterPack=*/false),
- Pattern(Pattern) { }
+ Pattern(Pattern),
+ NumExpansions(NumExpansions? *NumExpansions + 1: 0) { }
friend class ASTContext; // ASTContext creates these
-
+
public:
/// \brief Retrieve the pattern of this pack expansion, which is the
/// type that will be repeatedly instantiated when instantiating the
/// pack expansion itself.
QualType getPattern() const { return Pattern; }
+ /// \brief Retrieve the number of expansions that this pack expansion will
+ /// generate, if known.
+ llvm::Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+ }
+
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getPattern());
+ Profile(ID, getPattern(), getNumExpansions());
}
- static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern) {
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions) {
ID.AddPointer(Pattern.getAsOpaquePtr());
+ ID.AddBoolean(NumExpansions);
+ if (NumExpansions)
+ ID.AddInteger(*NumExpansions);
}
static bool classof(const Type *T) {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 8c3a57622b..a5a3d83833 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1868,6 +1868,9 @@ def err_pack_expansion_without_parameter_packs : Error<
def err_pack_expansion_length_conflict : Error<
"pack expansion contains parameter packs %0 and %1 that have different "
"lengths (%2 vs. %3)">;
+def err_pack_expansion_length_conflict_multilevel : Error<
+ "pack expansion contains parameter pack %0 that has a different "
+ "length (%1 vs. %2) from outer parameter packs">;
def err_pack_expansion_member_init : Error<
"pack expansion for initialization of member %0">;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 1b22cd8ad7..ee286ddf1d 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -3330,13 +3330,15 @@ public:
/// \brief Construct a pack expansion type from the pattern of the pack
/// expansion.
TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
- SourceLocation EllipsisLoc);
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions);
/// \brief Construct a pack expansion type from the pattern of the pack
/// expansion.
QualType CheckPackExpansion(QualType Pattern,
SourceRange PatternRange,
- SourceLocation EllipsisLoc);
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions);
/// \brief Invoked when parsing an expression followed by an ellipsis, which
/// creates a pack expansion.
@@ -3373,8 +3375,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
@@ -3387,7 +3393,7 @@ public:
const MultiLevelTemplateArgumentList &TemplateArgs,
bool &ShouldExpand,
bool &RetainExpansion,
- unsigned &NumExpansions);
+ llvm::Optional<unsigned> &NumExpansions);
/// \brief Determine the number of arguments in the given pack expansion
/// type.
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 35d4b7a097..a98e0636d4 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2246,9 +2246,10 @@ ASTContext::getDependentTemplateSpecializationType(
return QualType(T, 0);
}
-QualType ASTContext::getPackExpansionType(QualType Pattern) {
+QualType ASTContext::getPackExpansionType(QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions) {
llvm::FoldingSetNodeID ID;
- PackExpansionType::Profile(ID, Pattern);
+ PackExpansionType::Profile(ID, Pattern, NumExpansions);
assert(Pattern->containsUnexpandedParameterPack() &&
"Pack expansions must expand one or more parameter packs");
@@ -2260,13 +2261,13 @@ QualType ASTContext::getPackExpansionType(QualType Pattern) {
QualType Canon;
if (!Pattern.isCanonical()) {
- Canon = getPackExpansionType(getCanonicalType(Pattern));
+ Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions);
// Find the insert position again.
PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
}
- T = new (*this) PackExpansionType(Pattern, Canon);
+ T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions);
Types.push_back(T);
PackExpansionTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 6ad62eab30..bd91facd08 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -319,7 +319,8 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
QualType ArgType = Context.getTypeDeclType(TTP);
if (TTP->isParameterPack())
- ArgType = Context.getPackExpansionType(ArgType);
+ ArgType = Context.getPackExpansionType(ArgType,
+ llvm::Optional<unsigned>());
Arg = TemplateArgument(ArgType);
} else if (NonTypeTemplateParmDecl *NTTP =
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 42a936c500..f7c4ac832f 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -346,6 +346,7 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
TemplateArgumentLoc
TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
+ llvm::Optional<unsigned> &NumExpansions,
ASTContext &Context) const {
assert(Argument.isPackExpansion());
@@ -363,6 +364,7 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
Ellipsis = Expansion.getEllipsisLoc();
TypeLoc Pattern = Expansion.getPatternLoc();
+ NumExpansions = Expansion.getTypePtr()->getNumExpansions();
// FIXME: This is horrible. We know where the source location data is for
// the pattern, and we have the pattern's type, but we are forced to copy
@@ -382,10 +384,12 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
= cast<PackExpansionExpr>(Argument.getAsExpr());
Expr *Pattern = Expansion->getPattern();
Ellipsis = Expansion->getEllipsisLoc();
+ // FIXME: Variadic templates num expansions
return TemplateArgumentLoc(Pattern, Pattern);
}
case TemplateArgument::TemplateExpansion:
+ // FIXME: Variadic templates num expansions
Ellipsis = getTemplateEllipsisLoc();
return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
getTemplateQualifierRange(),
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>
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index edb79ee808..e7a3b0aebb 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2954,8 +2954,10 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
QualType Pattern = GetType(Record[0]);
if (Pattern.isNull())
return QualType();
-
- return Context->getPackExpansionType(Pattern);
+ llvm::Optional<unsigned> NumExpansions;
+ if (Record[1])
+ NumExpansions = Record[1] - 1;
+ return Context->getPackExpansionType(Pattern, NumExpansions);
}
case TYPE_ELABORATED: {
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 52cf3829dc..7582d1a450 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -316,6 +316,10 @@ ASTTypeWriter::VisitDependentTemplateSpecializationType(
void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) {
Writer.AddTypeRef(T->getPattern(), Record);
+ if (llvm::Optional<unsigned> NumExpansions = T-