diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 3 | ||||
-rw-r--r-- | include/clang/AST/TemplateBase.h | 4 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 34 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 16 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 9 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 3 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 63 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 6 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 4 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp | 13 |
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- |