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/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);
+}