Introduce a new type, PackExpansionType, to capture types that are
pack expansions, e.g. given

  template<typename... Types> struct tuple;

  template<typename... Types>
  struct tuple_of_refs {
    typedef tuple<Types&...> types;
  };

the type of the "types" typedef is a PackExpansionType whose pattern
is Types&. 

This commit introduces support for creating pack expansions for
template type arguments, as above, but not for any other kind of pack
expansion, nor for any form of instantiation.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122223 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5819362..36bb76f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2386,6 +2386,7 @@
 
     // If we have a template parameter pack, check every remaining template
     // argument against that template parameter pack.
+    // FIXME: Variadic templates are unimplemented
     if ((*Param)->isTemplateParameterPack()) {
       Diag(TemplateLoc, diag::err_variadic_templates_unsupported);
       return true;
@@ -2640,6 +2641,11 @@
   return VisitNestedNameSpecifier(T->getQualifier());
 }
 
+bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType(
+                                                   const PackExpansionType* T) {
+  return Visit(T->getPattern());
+}
+
 bool UnnamedLocalNoLinkageFinder::VisitObjCObjectType(const ObjCObjectType *) {
   return false;
 }
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index da04b62..d4e99e8 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2815,6 +2815,12 @@
                                  OnlyDeduced, Depth, Used);
     break;
 
+  case Type::PackExpansion:
+    MarkUsedTemplateParameters(SemaRef, 
+                               cast<PackExpansionType>(T)->getPattern(),
+                               OnlyDeduced, Depth, Used);
+    break;
+
   // None of these types have any template parameters in them.
   case Type::Builtin:
   case Type::VariableArray:
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index f190b3c..321f383 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -10,6 +10,7 @@
 //===----------------------------------------------------------------------===/
 
 #include "clang/Sema/Sema.h"
+#include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecursiveASTVisitor.h"
@@ -254,3 +255,62 @@
   return true;
 }
 
+ParsedTemplateArgument 
+Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
+                         SourceLocation EllipsisLoc) {
+  if (Arg.isInvalid())
+    return Arg;
+
+  switch (Arg.getKind()) {
+  case ParsedTemplateArgument::Type: {
+    TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
+    if (Result.isInvalid())
+      return ParsedTemplateArgument();
+
+    return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), 
+                                  Arg.getLocation());
+  }
+
+  case ParsedTemplateArgument::NonType:
+    Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
+      << 0;
+    return ParsedTemplateArgument();
+
+  case ParsedTemplateArgument::Template:
+    Diag(EllipsisLoc, diag::err_pack_expansion_unsupported)
+      << 1;
+    return ParsedTemplateArgument();
+  }
+  llvm_unreachable("Unhandled template argument kind?");
+  return ParsedTemplateArgument();
+}
+
+TypeResult Sema::ActOnPackExpansion(ParsedType Type, 
+                                    SourceLocation EllipsisLoc) {
+  TypeSourceInfo *TSInfo;
+  GetTypeFromParser(Type, &TSInfo);
+  if (!TSInfo)
+    return true;
+
+  // 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 (!TSInfo->getType()->containsUnexpandedParameterPack()) {
+    Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+      << TSInfo->getTypeLoc().getSourceRange();
+    return true;
+  }
+
+  // Create the pack expansion type and source-location information.
+  QualType Result = Context.getPackExpansionType(TSInfo->getType());
+  TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
+  PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
+  TL.setEllipsisLoc(EllipsisLoc);
+
+  // Copy over the source-location information from the type.
+  memcpy(TL.getNextTypeLoc().getOpaqueData(),
+         TSInfo->getTypeLoc().getOpaqueData(),
+         TSInfo->getTypeLoc().getFullDataSize());
+  return CreateParsedType(Result, TSResult);
+}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index f4a4ae2..a90ea39 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3506,6 +3506,15 @@
 }
 
 template<typename Derived>
+QualType TreeTransform<Derived>::TransformPackExpansionType(TypeLocBuilder &TLB,
+                                                      PackExpansionTypeLoc TL) {
+  // FIXME: Implement!
+  getSema().Diag(TL.getEllipsisLoc(), 
+                 diag::err_pack_expansion_instantiation_unsupported);
+  return QualType();
+}
+
+template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
                                                    ObjCInterfaceTypeLoc TL) {