Add an AST representation for non-type template parameter
packs, e.g.,

  template<typename T, unsigned ...Dims> struct multi_array;

along with semantic analysis support for finding unexpanded non-type
template parameter packs in types, expressions, and so on.

Template instantiation involving non-type template parameter packs
probably doesn't work yet. That'll come soon.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122527 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e20b1ed..eaf222c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -109,6 +109,7 @@
                                             SourceLocation(), NTTP->getDepth(),
                                             NTTP->getPosition(), 0, 
                                             getCanonicalType(NTTP->getType()),
+                                            NTTP->isParameterPack(),
                                             0));
     else
       CanonParams.push_back(getCanonicalTemplateTemplateParmDecl(
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 7ff217e..7d6c905 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -3414,7 +3414,7 @@
                                Importer.getToContext().getTranslationUnitDecl(),
                                          Loc, D->getDepth(), D->getPosition(),
                                          Name.getAsIdentifierInfo(),
-                                         T, TInfo);
+                                         T, D->isParameterPack(), TInfo);
 }
 
 Decl *
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 843e907..75ea2df 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -110,7 +110,9 @@
 bool Decl::isTemplateParameterPack() const {
   if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
     return TTP->isParameterPack();
-
+  if (const NonTypeTemplateParmDecl *NTTP
+                                = llvm::dyn_cast<NonTypeTemplateParmDecl>(this))
+    return NTTP->isParameterPack();
   return false;
 }
 
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 422e5e3..dff956c 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -390,8 +390,9 @@
 NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
                                 SourceLocation L, unsigned D, unsigned P,
                                 IdentifierInfo *Id, QualType T,
-                                TypeSourceInfo *TInfo) {
-  return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, TInfo);
+                                bool ParameterPack, TypeSourceInfo *TInfo) {
+  return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, ParameterPack,
+                                         TInfo);
 }
 
 SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 5d0e0e3..d8bb0af 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -208,8 +208,14 @@
   //          member of an unknown specialization.
   //        (handled by DependentScopeDeclRefExpr)
 
-  // FIXME: Variadic templates require that we compute whether this
-  // declaration reference contains an unexpanded parameter pack.
+  // Determine whether this expression contains any unexpanded parameter
+  // packs.
+  // Is the declaration a parameter pack?
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+    if (NTTP->isParameterPack())
+      ExprBits.ContainsUnexpandedParameterPack = true;
+  }
+  // FIXME: Variadic templates function parameter packs.
 }
 
 DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, 
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 7357e94..a487825 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -632,16 +632,12 @@
     Invalid = true;
   }
   
-  if (D.hasEllipsis()) {
-    // FIXME: Variadic templates.
-    Diag(D.getEllipsisLoc(), diag::err_non_type_parameter_pack_unsupported);
-    Invalid = true;
-  }
-      
+  bool IsParameterPack = D.hasEllipsis();
   NonTypeTemplateParmDecl *Param
     = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
                                       D.getIdentifierLoc(),
-                                      Depth, Position, ParamName, T, TInfo);
+                                      Depth, Position, ParamName, T, 
+                                      IsParameterPack, TInfo);
   if (Invalid)
     Param->setInvalidDecl();
 
@@ -652,7 +648,7 @@
   }
   
   // Check the well-formedness of the default template argument, if provided.
-  if (Default) {  
+  if (Default) {
     // Check for unexpanded parameter packs.
     if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
       return Param;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 54c5095..9db3a8c 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1506,11 +1506,12 @@
     Invalid = true;
   }
   
+  // FIXME: Variadic templates.
   NonTypeTemplateParmDecl *Param
     = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
                                     D->getDepth() - TemplateArgs.getNumLevels(), 
                                       D->getPosition(), D->getIdentifier(), T, 
-                                      DI);
+                                      D->isParameterPack(), DI);
   if (Invalid)
     Param->setInvalidDecl();
   
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index d9c7e72..fe30ba5 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -63,8 +63,21 @@
       return true;
     }
 
-    // FIXME: Record occurrences of non-type and template template
-    // parameter packs.
+    /// \brief Record occurrences of (FIXME: function and) non-type template
+    /// parameter packs in an expression.
+    bool VisitDeclRefExpr(DeclRefExpr *E) {
+      if (NonTypeTemplateParmDecl *NTTP 
+                            = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
+        if (NTTP->isParameterPack())
+          Unexpanded.push_back(std::make_pair(NTTP, E->getLocation()));
+      }
+      
+      // FIXME: Function parameter packs.
+      
+      return true;
+    }
+    
+    // FIXME: Record occurrences of template template parameter packs.
 
     // FIXME: Once we have pack expansions in the AST, block their
     // traversal.
@@ -95,8 +108,8 @@
     /// \brief Suppress traversel into types with location information
     /// that do not contain unexpanded parameter packs.
     bool TraverseTypeLoc(TypeLoc TL) {
-      if (!TL.getType().isNull() && TL.
-          getType()->containsUnexpandedParameterPack())
+      if (!TL.getType().isNull() && 
+          TL.getType()->containsUnexpandedParameterPack())
         return inherited::TraverseTypeLoc(TL);
 
       return true;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index e693c8d..46ec0fe 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1504,6 +1504,8 @@
       // it expands those parameter packs.
       if (T->containsUnexpandedParameterPack())
         T = Context.getPackExpansionType(T);
+      else if (!getLangOptions().CPlusPlus0x)
+        Diag(D.getEllipsisLoc(), diag::err_variadic_templates);
       break;
     
     case Declarator::FileContext:
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 6100d65..f2183ea 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1156,6 +1156,7 @@
   D->setDepth(Record[Idx++]);
   D->setPosition(Record[Idx++]);
   // Rest of NonTypeTemplateParmDecl.
+  D->ParameterPack = Record[Idx++];
   if (Record[Idx++]) {
     Expr *DefArg = Reader.ReadExpr(F);
     bool Inherited = Record[Idx++];
@@ -1429,7 +1430,7 @@
     break;
   case DECL_NON_TYPE_TEMPLATE_PARM:
     D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
-                                        QualType(),0);
+                                        QualType(), false, 0);
     break;
   case DECL_TEMPLATE_TEMPLATE_PARM:
     D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(),0,0,0,0);
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index aa145c4..add6cd3 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -994,6 +994,7 @@
   Record.push_back(D->getDepth());
   Record.push_back(D->getPosition());
   // Rest of NonTypeTemplateParmDecl.
+  Record.push_back(D->isParameterPack());
   Record.push_back(D->getDefaultArgument() != 0);
   if (D->getDefaultArgument()) {
     Writer.AddStmt(D->getDefaultArgument());