diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-12-20 02:24:11 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-12-20 02:24:11 +0000 |
commit | 7536dd5e6c99584481b7dab68b7e7d8df9c54054 (patch) | |
tree | b404f8a27369f14746fb159940fda899f9355cae /lib/Sema/SemaTemplateVariadic.cpp | |
parent | d3d3be9bc717b37366324e9711f1ea22dea42caa (diff) |
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
Diffstat (limited to 'lib/Sema/SemaTemplateVariadic.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index f190b3c774..321f38397d 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 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, 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); +} |