]> granicus.if.org Git - clang/commitdiff
Keep track of the number of expansions to be produced from a type pack
authorDouglas Gregor <dgregor@apple.com>
Fri, 14 Jan 2011 17:04:44 +0000 (17:04 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 14 Jan 2011 17:04:44 +0000 (17:04 +0000)
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

16 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/TemplateBase.h
include/clang/AST/Type.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/AST/ASTContext.cpp
lib/AST/DeclTemplate.cpp
lib/AST/TemplateBase.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/SemaTemplateVariadic.cpp
lib/Sema/SemaType.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp

index 15bc301bd923b0a0acb8420847f4c62777f713b8..93b793eb784bfbe68d6ab115a369a5dcdec19a7d 100644 (file)
@@ -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;
 
index 649c005020228c7116dd7198f0f2b8ec3cbb2099..93ec35bebe689a839382896fe09d26276b397ba6 100644 (file)
@@ -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;
 };
 
index c081a161de535cde00167dc57bcbf5652d8b77f7..e32676a3973d42e77d2d7cb13f5e01a2976abf1f 100644 (file)
@@ -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) {
index 8c3a57622b00768a3833565d3d9cdbee36c90c36..a5a3d83833149d6f2e6e7a2f6ad1594cad16f705 100644 (file)
@@ -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">;
 
index 1b22cd8ad71aeca724680a4407ffa466d2c2b450..ee286ddf1dba25294553933b60015c61c630dabb 100644 (file)
@@ -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.
index 35d4b7a097392d65c34b816bbf9f146a2f9769d1..a98e0636d493896518dbfae1eec8e34ef95741bb 100644 (file)
@@ -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);  
index 6ad62eab30f0cbac0ec68e027d3c6a45e5803438..bd91facd08f75fb17b00abeb1c7c7ac91ebb1c72 100644 (file)
@@ -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 =
index 42a936c50098e600f14990038696fec1ad4fdb92..f7c4ac832f843f9041e5612d84ac35b0fc77ddcc 100644 (file)
@@ -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(),
index 629dc589588c742052e41bdaa3a303cb3888f849..c181a568b52752f7f39d69949e5d13989ac1beb5 100644 (file)
@@ -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(),
index a18bfbafc079522c4be85a4002dda927dc39457a..6b5713a2fa2ddc84c1f1f7a28937c9041dbbb21c 100644 (file)
@@ -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.
index dc5013c25d8e89cf3881c24be3c7cfffcbfd8478..899b58e5587c843d7b5fcbb407e43e83eee13fb5 100644 (file)
@@ -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;
     }
   }
index ada8a1d8a2a64c547e019a1bc71189caf77b6cfc..e843ca5fca131a7d0e9192853ef7bf5c0b1ea5d6 100644 (file)
@@ -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;
index 4127d5045ac822998f48db8f4b6257d151d6d4ea..f2496c2f1aebc7721ba19a6431ce9b9c766cdb7a 100644 (file)
@@ -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>
index edb79ee808d9ed1ea3f3dcc43daf61f50f215423..e7a3b0aebb0208dc33f2a3c09fa3e1996ef7e5bc 100644 (file)
@@ -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: {
index 52cf3829dc9385b226c4d5b2efc8fc084f43fd77..7582d1a4502fe2c6410a6569fe4cfd3f8eb9b5cc 100644 (file)
@@ -316,6 +316,10 @@ ASTTypeWriter::VisitDependentTemplateSpecializationType(
 
 void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) {
   Writer.AddTypeRef(T->getPattern(), Record);
+  if (llvm::Optional<unsigned> NumExpansions = T->getNumExpansions())
+    Record.push_back(*NumExpansions + 1);
+  else
+    Record.push_back(0);
   Code = TYPE_PACK_EXPANSION;
 }
 
index ff2134dc33c0e35f82ba2fea75853c4ada27690d..a01ffc338fb074965bfd4fda26292f1fe7322df4 100644 (file)
@@ -18,16 +18,23 @@ namespace PacksAtDifferentLevels {
 
   template<typename ...Types>
   struct X {
-    template<typename> struct Inner;
+    template<typename> struct Inner {
+      static const unsigned value = 1;
+    };
 
     template<typename ...YTypes>
     struct Inner<tuple<pair<Types, YTypes>...> > {
-      static const unsigned zero = sizeof...(Types) - sizeof...(YTypes);
+      static const unsigned value = sizeof...(Types) - sizeof...(YTypes);
     };
   };
 
   int check0[X<short, int, long>::Inner<tuple<pair<short, unsigned short>,
                                              pair<int, unsigned int>,
                                              pair<long, unsigned long>>
-                                       >::zero == 0? 1 : -1];
+                                       >::value == 0? 1 : -1];
+
+  int check1[X<short, int>::Inner<tuple<pair<short, unsigned short>,
+                                        pair<int, unsigned int>,
+                                        pair<long, unsigned long>>
+                                       >::value == 1? 1 : -1]; 
 }