Implement support for pack expansions whose pattern is a non-type
template argument (described by an expression, of course). For
example:

  template<int...> struct int_tuple { };

  template<int ...Values>
  struct square {
    typedef int_tuple<(Values*Values)...> type;
  };

It also lays the foundation for pack expansions in an initializer-list.
  



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122751 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index cbd33f2..4592e5f 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -1025,3 +1025,15 @@
 Stmt::child_iterator CXXNoexceptExpr::child_end() {
   return child_iterator(&Operand + 1);
 }
+
+SourceRange PackExpansionExpr::getSourceRange() const {
+  return SourceRange(Pattern->getLocStart(), EllipsisLoc);
+}
+
+Stmt::child_iterator PackExpansionExpr::child_begin() {
+  return child_iterator(&Pattern);
+}
+
+Stmt::child_iterator PackExpansionExpr::child_end() {
+  return child_iterator(&Pattern + 1);
+}
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 4cf393d..f437804 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -304,6 +304,9 @@
       
   case Expr::CXXUuidofExprClass:
     return Cl::CL_LValue;
+      
+  case Expr::PackExpansionExprClass:
+    return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern());
   }
   
   llvm_unreachable("unhandled expression kind in classification");
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 8797880..c39b398 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -2634,6 +2634,7 @@
   case Expr::BlockDeclRefExprClass:
   case Expr::NoStmtClass:
   case Expr::OpaqueValueExprClass:
+  case Expr::PackExpansionExprClass:
     return ICEDiag(2, E->getLocStart());
 
   case Expr::GNUNullExprClass:
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 6bbe8f9..cc90526 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1246,6 +1246,11 @@
   OS << ")";
 }
 
+void StmtPrinter::VisitPackExpansionExpr(clang::PackExpansionExpr *E) {
+  PrintExpr(E->getPattern());
+  OS << "...";
+}
+
 // Obj-C
 
 void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 66c067b..820eb06 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -832,6 +832,10 @@
   VisitExpr(S);
 }
 
+void StmtProfiler::VisitPackExpansionExpr(PackExpansionExpr *S) {
+  VisitExpr(S);
+}
+
 void StmtProfiler::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);  
 }
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 04e8a38..c971519 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -72,15 +73,14 @@
     return false;
       
   case Type:
-    return llvm::isa<PackExpansionType>(getAsType());
+    return isa<PackExpansionType>(getAsType());
       
   case Template:
     // FIXME: Template template pack expansions.
     break;
     
   case Expression:
-    // FIXME: Expansion pack expansions.
-    break;  
+    return isa<PackExpansionExpr>(getAsExpr());
   }
   
   return false;
@@ -199,9 +199,11 @@
       return getAsType()->getAs<PackExpansionType>()->getPattern();
       
     case Expression:
+      return cast<PackExpansionExpr>(getAsExpr())->getPattern();
+      
     case Template:
       // FIXME: Variadic templates.
-      llvm_unreachable("Expression and template pack expansions unsupported");
+      llvm_unreachable("Template pack expansions unsupported");
       
     case Declaration:
     case Integral:
@@ -343,10 +345,14 @@
                                PatternTSInfo);
   }
       
-  case TemplateArgument::Expression:
+  case TemplateArgument::Expression: {
+    Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
+    return TemplateArgumentLoc(Pattern, Pattern);
+  }
+      
   case TemplateArgument::Template:
     // FIXME: Variadic templates.
-      llvm_unreachable("Expression and template pack expansions unsupported");
+      llvm_unreachable("Template pack expansions unsupported");
     
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index a45403e..0aa9f40 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -2043,7 +2043,11 @@
     Out << "LDnE";
     break;
   }
-
+      
+  case Expr::PackExpansionExprClass:
+    Out << "sp";
+    mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
+    break;
   }
 }
 
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 4a667cd..99b6dac 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2926,6 +2926,10 @@
                            bool OnlyDeduced,
                            unsigned Depth,
                            llvm::SmallVectorImpl<bool> &Used) {
+  // We can deduce from a pack expansion.
+  if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
+    E = Expansion->getPattern();
+      
   // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to 
   // find other occurrences of template parameters.
   const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 3dac8a0..030a042 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -79,9 +79,6 @@
     
     // FIXME: Record occurrences of template template parameter packs.
 
-    // FIXME: Once we have pack expansions in the AST, block their
-    // traversal.
-
     //------------------------------------------------------------------------
     // Pruning the search for unexpanded parameter packs.
     //------------------------------------------------------------------------
@@ -299,14 +296,17 @@
                                   Arg.getLocation());
   }
 
-  case ParsedTemplateArgument::NonType:
-    Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
-      << 0;
-    return ParsedTemplateArgument();
-
+  case ParsedTemplateArgument::NonType: {
+    ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc);
+    if (Result.isInvalid())
+      return ParsedTemplateArgument();
+    
+    return ParsedTemplateArgument(Arg.getKind(), Result.get(), 
+                                  Arg.getLocation());
+  }
+    
   case ParsedTemplateArgument::Template:
-    Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
-      << 1;
+    Diag(EllipsisLoc, diag::err_pack_expansion_unsupported);
     return ParsedTemplateArgument();
   }
   llvm_unreachable("Unhandled template argument kind?");
@@ -352,6 +352,24 @@
   return TSResult;
 }
 
+ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
+  if (!Pattern)
+    return ExprError();
+  
+  // 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
+  //   expansion.
+  if (!Pattern->containsUnexpandedParameterPack()) {
+    Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+    << Pattern->getSourceRange();
+    return ExprError();
+  }
+  
+  // Create the pack expansion expression and source-location information.
+  return Owned(new (Context) PackExpansionExpr(Context.DependentTy, Pattern,
+                                               EllipsisLoc));
+}
 
 bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
                                            SourceRange PatternRange,
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index de13084..992b849 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -6439,6 +6439,13 @@
 
 template<typename Derived>
 ExprResult
+TreeTransform<Derived>::TransformPackExpansionExpr(PackExpansionExpr *E) {
+  llvm_unreachable("pack expansion expression in unhandled context");
+  return ExprError();
+}
+  
+template<typename Derived>
+ExprResult
 TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
   return SemaRef.Owned(E);
 }
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index aa669b3..4703c63 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -176,7 +176,8 @@
     void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
     void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
     void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
-
+    void VisitPackExpansionExpr(PackExpansionExpr *E);
+    
     void VisitOpaqueValueExpr(OpaqueValueExpr *E);
   };
 }
@@ -1287,6 +1288,12 @@
   E->Operand = Reader.ReadSubExpr();
 }
 
+void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) {
+  VisitExpr(E);
+  E->EllipsisLoc = ReadSourceLocation(Record, Idx);
+  E->Pattern = Reader.ReadSubExpr();  
+}
+
 void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);
 }
@@ -1809,6 +1816,10 @@
       S = new (Context) CXXNoexceptExpr(Empty);
       break;
 
+    case EXPR_PACK_EXPANSION:
+      S = new (Context) PackExpansionExpr(Empty);
+      break;
+        
     case EXPR_OPAQUE_VALUE:
       S = new (Context) OpaqueValueExpr(Empty);
       break;
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 89c293f..27261db 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -150,7 +150,7 @@
     void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
     void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
     void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
-
+    void VisitPackExpansionExpr(PackExpansionExpr *E);
     void VisitOpaqueValueExpr(OpaqueValueExpr *E);
   };
 }
@@ -1296,6 +1296,13 @@
   Code = serialization::EXPR_CXX_NOEXCEPT;
 }
 
+void ASTStmtWriter::VisitPackExpansionExpr(PackExpansionExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getEllipsisLoc(), Record);
+  Writer.AddStmt(E->getPattern());
+  Code = serialization::EXPR_PACK_EXPANSION;
+}
+
 void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);
   Code = serialization::EXPR_OPAQUE_VALUE;
diff --git a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
index c522e72..9fef6d8 100644
--- a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -771,6 +771,7 @@
     case Stmt::UnresolvedLookupExprClass:
     case Stmt::UnresolvedMemberExprClass:
     case Stmt::CXXNoexceptExprClass:
+    case Stmt::PackExpansionExprClass:
     {
       SaveAndRestore<bool> OldSink(Builder->BuildSinks);
       Builder->BuildSinks = true;