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) {