Introduce a new kind of TemplateName that captures a substituted

template template parameter pack that cannot be fully expanded because
its enclosing pack expansion could not be expanded. This form of
TemplateName plays the same role as SubstTemplateTypeParmPackType and
SubstNonTypeTemplateParmPackExpr do for template type parameter packs
and non-type template parameter packs, respectively.

We should now handle these multi-level pack expansion substitutions
anywhere. The largest remaining gap in our variadic-templates support
is that we cannot cope with non-type template parameter packs whose
type is a pack expansion.

llvm-svn: 123521
This commit is contained in:
Douglas Gregor 2011-01-15 06:45:20 +00:00
parent 9c10d587f6
commit 5590be0491
14 changed files with 354 additions and 38 deletions

View File

@ -119,7 +119,9 @@ class ASTContext {
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
mutable llvm::FoldingSet<SubstTemplateTemplateParmPackStorage>
SubstTemplateTemplateParmPacks;
/// \brief The set of nested name specifiers. /// \brief The set of nested name specifiers.
/// ///
/// This set is managed by the NestedNameSpecifier class. /// This set is managed by the NestedNameSpecifier class.
@ -936,7 +938,9 @@ public:
const IdentifierInfo *Name) const; const IdentifierInfo *Name) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
OverloadedOperatorKind Operator) const; OverloadedOperatorKind Operator) const;
TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
const TemplateArgument &ArgPack) const;
enum GetBuiltinTypeError { enum GetBuiltinTypeError {
GE_None, //< No error GE_None, //< No error
GE_Missing_stdio, //< Missing a type from <stdio.h> GE_Missing_stdio, //< Missing a type from <stdio.h>

View File

@ -23,27 +23,67 @@ namespace llvm {
} }
namespace clang { namespace clang {
class ASTContext;
class DependentTemplateName; class DependentTemplateName;
class DiagnosticBuilder; class DiagnosticBuilder;
class IdentifierInfo; class IdentifierInfo;
class NestedNameSpecifier; class NestedNameSpecifier;
class OverloadedTemplateStorage;
struct PrintingPolicy; struct PrintingPolicy;
class QualifiedTemplateName; class QualifiedTemplateName;
class NamedDecl; class NamedDecl;
class SubstTemplateTemplateParmPackStorage;
class TemplateArgument;
class TemplateDecl; class TemplateDecl;
class TemplateTemplateParmDecl;
/// \brief A structure for storing the information associated with an
/// overloaded template name. /// \brief Implementation class used to describe either a set of overloaded
class OverloadedTemplateStorage { /// template names or an already-substituted template template parameter pack.
class UncommonTemplateNameStorage {
protected:
union { union {
unsigned Size; struct {
/// \brief If true, this is an OverloadedTemplateStorage instance;
/// otherwise, it's a SubstTemplateTemplateParmPackStorage instance.
unsigned IsOverloadedStorage : 1;
/// \brief The number of stored templates or template arguments,
/// depending on which subclass we have.
unsigned Size : 31;
} Bits;
void *PointerAlignment; void *PointerAlignment;
}; };
UncommonTemplateNameStorage(unsigned Size, bool OverloadedStorage) {
Bits.IsOverloadedStorage = OverloadedStorage;
Bits.Size = Size;
}
public:
unsigned size() const { return Bits.Size; }
OverloadedTemplateStorage *getAsOverloadedStorage() {
return Bits.IsOverloadedStorage
? reinterpret_cast<OverloadedTemplateStorage *>(this)
: 0;
}
SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
return Bits.IsOverloadedStorage
? 0
: reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) ;
}
};
/// \brief A structure for storing the information associated with an
/// overloaded template name.
class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext; friend class ASTContext;
OverloadedTemplateStorage(unsigned Size) : Size(Size) {} OverloadedTemplateStorage(unsigned Size)
: UncommonTemplateNameStorage(Size, true) { }
NamedDecl **getStorage() { NamedDecl **getStorage() {
return reinterpret_cast<NamedDecl **>(this + 1); return reinterpret_cast<NamedDecl **>(this + 1);
@ -55,11 +95,47 @@ class OverloadedTemplateStorage {
public: public:
typedef NamedDecl *const *iterator; typedef NamedDecl *const *iterator;
unsigned size() const { return Size; }
iterator begin() const { return getStorage(); } iterator begin() const { return getStorage(); }
iterator end() const { return getStorage() + size(); } iterator end() const { return getStorage() + size(); }
}; };
/// \brief A structure for storing an already-substituted template template
/// parameter pack.
///
/// This kind of template names occurs when the parameter pack has been
/// provided with a template template argument pack in a context where its
/// enclosing pack expansion could not be fully expanded.
class SubstTemplateTemplateParmPackStorage
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode
{
ASTContext &Context;
TemplateTemplateParmDecl *Parameter;
const TemplateArgument *Arguments;
public:
SubstTemplateTemplateParmPackStorage(ASTContext &Context,
TemplateTemplateParmDecl *Parameter,
unsigned Size,
const TemplateArgument *Arguments)
: UncommonTemplateNameStorage(Size, false), Context(Context),
Parameter(Parameter), Arguments(Arguments) { }
/// \brief Retrieve the template template parameter pack being substituted.
TemplateTemplateParmDecl *getParameterPack() const {
return Parameter;
}
/// \brief Retrieve the template template argument pack with which this
/// parameter was substituted.
TemplateArgument getArgumentPack() const;
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
TemplateTemplateParmDecl *Parameter,
const TemplateArgument &ArgPack);
};
/// \brief Represents a C++ template name within the type system. /// \brief Represents a C++ template name within the type system.
/// ///
@ -90,7 +166,7 @@ public:
/// only be understood in the context of /// only be understood in the context of
class TemplateName { class TemplateName {
typedef llvm::PointerUnion4<TemplateDecl *, typedef llvm::PointerUnion4<TemplateDecl *,
OverloadedTemplateStorage *, UncommonTemplateNameStorage *,
QualifiedTemplateName *, QualifiedTemplateName *,
DependentTemplateName *> StorageType; DependentTemplateName *> StorageType;
@ -103,16 +179,28 @@ class TemplateName {
public: public:
// \brief Kind of name that is actually stored. // \brief Kind of name that is actually stored.
enum NameKind { enum NameKind {
/// \brief A single template declaration.
Template, Template,
/// \brief A set of overloaded template declarations.
OverloadedTemplate, OverloadedTemplate,
/// \brief A qualified template name, where the qualification is kept
/// to describe the source code as written.
QualifiedTemplate, QualifiedTemplate,
DependentTemplate /// \brief A dependent template name that has not been resolved to a
/// template (or set of templates).
DependentTemplate,
/// \brief A template template parameter pack that has been substituted for
/// a template template argument pack, but has not yet been expanded into
/// individual arguments.
SubstTemplateTemplateParmPack
}; };
TemplateName() : Storage() { } TemplateName() : Storage() { }
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
explicit TemplateName(OverloadedTemplateStorage *Storage) explicit TemplateName(OverloadedTemplateStorage *Storage)
: Storage(Storage) { } : Storage(Storage) { }
explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
: Storage(Storage) { }
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { } explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
@ -122,7 +210,7 @@ public:
// \brief Get the kind of name that is actually stored. // \brief Get the kind of name that is actually stored.
NameKind getKind() const; NameKind getKind() const;
/// \brief Retrieve the the underlying template declaration that /// \brief Retrieve the underlying template declaration that
/// this template name refers to, if known. /// this template name refers to, if known.
/// ///
/// \returns The template declaration that this template name refers /// \returns The template declaration that this template name refers
@ -131,7 +219,7 @@ public:
/// set of function templates, returns NULL. /// set of function templates, returns NULL.
TemplateDecl *getAsTemplateDecl() const; TemplateDecl *getAsTemplateDecl() const;
/// \brief Retrieve the the underlying, overloaded function template /// \brief Retrieve the underlying, overloaded function template
// declarations that this template name refers to, if known. // declarations that this template name refers to, if known.
/// ///
/// \returns The set of overloaded function templates that this template /// \returns The set of overloaded function templates that this template
@ -139,7 +227,25 @@ public:
/// specific set of function templates because it is a dependent name or /// specific set of function templates because it is a dependent name or
/// refers to a single template, returns NULL. /// refers to a single template, returns NULL.
OverloadedTemplateStorage *getAsOverloadedTemplate() const { OverloadedTemplateStorage *getAsOverloadedTemplate() const {
return Storage.dyn_cast<OverloadedTemplateStorage *>(); if (UncommonTemplateNameStorage *Uncommon =
Storage.dyn_cast<UncommonTemplateNameStorage *>())
return Uncommon->getAsOverloadedStorage();
return 0;
}
/// \brief Retrieve the substituted template template parameter pack, if
/// known.
///
/// \returns The storage for the substituted template template parameter pack,
/// if known. Otherwise, returns NULL.
SubstTemplateTemplateParmPackStorage *
getAsSubstTemplateTemplateParmPack() const {
if (UncommonTemplateNameStorage *Uncommon =
Storage.dyn_cast<UncommonTemplateNameStorage *>())
return Uncommon->getAsSubstTemplateTemplateParmPack();
return 0;
} }
/// \brief Retrieve the underlying qualified template name /// \brief Retrieve the underlying qualified template name

View File

@ -1885,10 +1885,6 @@ def err_ellipsis_in_declarator_not_parameter : Error<
def err_sizeof_pack_no_pack_name : Error< def err_sizeof_pack_no_pack_name : Error<
"%0 does not refer to the name of a parameter pack">; "%0 does not refer to the name of a parameter pack">;
// Unsupported variadic templates features
def err_pack_expansion_mismatch_unsupported : Error<
"clang cannot yet instantiate pack expansions with mismatched pack levels">;
def err_unexpected_typedef : Error< def err_unexpected_typedef : Error<
"unexpected type name %0: expected expression">; "unexpected type name %0: expected expression">;
def err_unexpected_namespace : Error< def err_unexpected_namespace : Error<

View File

@ -1073,7 +1073,8 @@ public:
unsigned &Idx); unsigned &Idx);
/// \brief Read a template name. /// \brief Read a template name.
TemplateName ReadTemplateName(const RecordData &Record, unsigned &Idx); TemplateName ReadTemplateName(PerFileData &F, const RecordData &Record,
unsigned &Idx);
/// \brief Read a template argument. /// \brief Read a template argument.
TemplateArgument ReadTemplateArgument(PerFileData &F, TemplateArgument ReadTemplateArgument(PerFileData &F,

View File

@ -2737,6 +2737,15 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const {
return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl())); return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl()));
} }
if (SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack()) {
TemplateTemplateParmDecl *CanonParam
= getCanonicalTemplateTemplateParmDecl(SubstPack->getParameterPack());
TemplateArgument CanonArgPack
= getCanonicalTemplateArgument(SubstPack->getArgumentPack());
return getSubstTemplateTemplateParmPack(CanonParam, CanonArgPack);
}
assert(!Name.getAsOverloadedTemplate()); assert(!Name.getAsOverloadedTemplate());
DependentTemplateName *DTN = Name.getAsDependentTemplateName(); DependentTemplateName *DTN = Name.getAsDependentTemplateName();
@ -4344,6 +4353,27 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
return TemplateName(QTN); return TemplateName(QTN);
} }
TemplateName
ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
const TemplateArgument &ArgPack) const {
ASTContext &Self = const_cast<ASTContext &>(*this);
llvm::FoldingSetNodeID ID;
SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack);
void *InsertPos = 0;
SubstTemplateTemplateParmPackStorage *Subst
= SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos);
if (!Subst) {
Subst = new (*this) SubstTemplateTemplateParmPackStorage(Self, Param,
ArgPack.pack_size(),
ArgPack.pack_begin());
SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos);
}
return TemplateName(Subst);
}
/// getFromTargetType - Given one of the integer types provided by /// getFromTargetType - Given one of the integer types provided by
/// TargetInfo, produce the corresponding type. The unsigned @p Type /// TargetInfo, produce the corresponding type. The unsigned @p Type
/// is actually a value of type @c TargetInfo::IntType. /// is actually a value of type @c TargetInfo::IntType.

View File

@ -4079,6 +4079,24 @@ TemplateName ASTImporter::Import(TemplateName From) {
return ToContext.getDependentTemplateName(Qualifier, DTN->getOperator()); return ToContext.getDependentTemplateName(Qualifier, DTN->getOperator());
} }
case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *SubstPack
= From.getAsSubstTemplateTemplateParmPack();
TemplateTemplateParmDecl *Param
= cast_or_null<TemplateTemplateParmDecl>(
Import(SubstPack->getParameterPack()));
if (!Param)
return TemplateName();
ASTNodeImporter Importer(*this);
TemplateArgument ArgPack
= Importer.ImportTemplateArgument(SubstPack->getArgumentPack());
if (ArgPack.isNull())
return TemplateName();
return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack);
}
} }
llvm_unreachable("Invalid template name kind"); llvm_unreachable("Invalid template name kind");

View File

@ -1017,6 +1017,12 @@ void CXXNameMangler::mangleType(TemplateName TN) {
break; break;
} }
case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *SubstPack
= TN.getAsSubstTemplateTemplateParmPack();
mangleTemplateParameter(SubstPack->getParameterPack()->getIndex());
break;
}
} }
addSubstitution(TN); addSubstitution(TN);

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/AST/TemplateName.h" #include "clang/AST/TemplateName.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclTemplate.h"
#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h" #include "clang/AST/PrettyPrinter.h"
@ -21,15 +22,33 @@
using namespace clang; using namespace clang;
using namespace llvm; using namespace llvm;
TemplateArgument
SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
return TemplateArgument(Arguments, size());
}
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
}
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context,
TemplateTemplateParmDecl *Parameter,
const TemplateArgument &ArgPack) {
ID.AddPointer(Parameter);
ArgPack.Profile(ID, Context);
}
TemplateName::NameKind TemplateName::getKind() const { TemplateName::NameKind TemplateName::getKind() const {
if (Storage.is<TemplateDecl *>()) if (Storage.is<TemplateDecl *>())
return Template; return Template;
if (Storage.is<OverloadedTemplateStorage *>()) if (Storage.is<DependentTemplateName *>())
return OverloadedTemplate; return DependentTemplate;
if (Storage.is<QualifiedTemplateName *>()) if (Storage.is<QualifiedTemplateName *>())
return QualifiedTemplate; return QualifiedTemplate;
assert(Storage.is<DependentTemplateName *>() && "There's a case unhandled!");
return DependentTemplate; return getAsOverloadedTemplate()? OverloadedTemplate
: SubstTemplateTemplateParmPack;
} }
TemplateDecl *TemplateName::getAsTemplateDecl() const { TemplateDecl *TemplateName::getAsTemplateDecl() const {
@ -73,7 +92,7 @@ bool TemplateName::containsUnexpandedParameterPack() const {
return DTN->getQualifier() && return DTN->getQualifier() &&
DTN->getQualifier()->containsUnexpandedParameterPack(); DTN->getQualifier()->containsUnexpandedParameterPack();
return false; return getAsSubstTemplateTemplateParmPack() != 0;
} }
void void
@ -96,7 +115,9 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
OS << DTN->getIdentifier()->getName(); OS << DTN->getIdentifier()->getName();
else else
OS << "operator " << getOperatorSpelling(DTN->getOperator()); OS << "operator " << getOperatorSpelling(DTN->getOperator());
} } else if (SubstTemplateTemplateParmPackStorage *SubstPack
= getAsSubstTemplateTemplateParmPack())
OS << SubstPack->getParameterPack()->getNameAsString();
} }
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,

View File

@ -697,6 +697,10 @@ namespace {
ElaboratedTypeKeyword Keyword, ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS, QualType T); NestedNameSpecifier *NNS, QualType T);
TemplateName TransformTemplateName(TemplateName Name,
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = 0);
ExprResult TransformPredefinedExpr(PredefinedExpr *E); ExprResult TransformPredefinedExpr(PredefinedExpr *E);
ExprResult TransformDeclRefExpr(DeclRefExpr *E); ExprResult TransformDeclRefExpr(DeclRefExpr *E);
ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E); ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
@ -762,12 +766,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
assert(Arg.getKind() == TemplateArgument::Pack && assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack"); "Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1) { assert(getSema().ArgumentPackSubstitutionIndex >= 0);
// FIXME: Variadic templates fun case.
getSema().Diag(Loc, diag::err_pack_expansion_mismatch_unsupported);
return 0;
}
assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
} }
@ -887,6 +886,60 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
NNS, T); NNS, T);
} }
TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
// If the corresponding template argument is NULL or non-existent, it's
// because we are performing instantiation from explicitly-specified
// template arguments in a function template, but there were some
// arguments left unspecified.
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
TTP->getPosition()))
return Name;
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1) {
// We have the template argument pack to substitute, but we're not
// actually expanding the enclosing pack expansion yet. So, just
// keep the entire argument pack.
return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
}
assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
}
TemplateName Template = Arg.getAsTemplate();
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
"Wrong kind of template template argument");
return Template;
}
}
if (SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack()) {
if (getSema().ArgumentPackSubstitutionIndex == -1)
return Name;
const TemplateArgument &ArgPack = SubstPack->getArgumentPack();
assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() &&
"Pack substitution index out-of-range");
return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex]
.getAsTemplate();
}
return inherited::TransformTemplateName(Name, ObjectType,
FirstQualifierInScope);
}
ExprResult ExprResult
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent()) if (!E->isTypeDependent())

View File

@ -891,7 +891,19 @@ public:
TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator, OverloadedOperatorKind Operator,
QualType ObjectType); QualType ObjectType);
/// \brief Build a new template name given a template template parameter pack
/// and the
///
/// By default, performs semantic analysis to determine whether the name can
/// be resolved to a specific template, then builds the appropriate kind of
/// template name. Subclasses may override this routine to provide different
/// behavior.
TemplateName RebuildTemplateName(TemplateTemplateParmDecl *Param,
const TemplateArgument &ArgPack) {
return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
}
/// \brief Build a new compound statement. /// \brief Build a new compound statement.
/// ///
/// By default, performs semantic analysis to build the new statement. /// By default, performs semantic analysis to build the new statement.
@ -2590,6 +2602,22 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
return TemplateName(TransTemplate); return TemplateName(TransTemplate);
} }
if (SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack()) {
TemplateTemplateParmDecl *TransParam
= cast_or_null<TemplateTemplateParmDecl>(
getDerived().TransformDecl(Loc, SubstPack->getParameterPack()));
if (!TransParam)
return TemplateName();
if (!getDerived().AlwaysRebuild() &&
TransParam == SubstPack->getParameterPack())
return Name;
return getDerived().RebuildTemplateName(TransParam,
SubstPack->getArgumentPack());
}
// These should be getting filtered out before they reach the AST. // These should be getting filtered out before they reach the AST.
llvm_unreachable("overloaded function decl survived to here"); llvm_unreachable("overloaded function decl survived to here");
return TemplateName(); return TemplateName();

View File

@ -3082,7 +3082,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
case TYPE_TEMPLATE_SPECIALIZATION: { case TYPE_TEMPLATE_SPECIALIZATION: {
unsigned Idx = 0; unsigned Idx = 0;
bool IsDependent = Record[Idx++]; bool IsDependent = Record[Idx++];
TemplateName Name = ReadTemplateName(Record, Idx); TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx);
llvm::SmallVector<TemplateArgument, 8> Args; llvm::SmallVector<TemplateArgument, 8> Args;
ReadTemplateArgumentList(Args, *Loc.F, Record, Idx); ReadTemplateArgumentList(Args, *Loc.F, Record, Idx);
QualType Canon = GetType(Record[Idx++]); QualType Canon = GetType(Record[Idx++]);
@ -4238,7 +4238,8 @@ void ASTReader::ReadQualifierInfo(PerFileData &F, QualifierInfo &Info,
} }
TemplateName TemplateName
ASTReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) { ASTReader::ReadTemplateName(PerFileData &F, const RecordData &Record,
unsigned &Idx) {
TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
switch (Kind) { switch (Kind) {
case TemplateName::Template: case TemplateName::Template:
@ -4268,6 +4269,19 @@ ASTReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
return Context->getDependentTemplateName(NNS, return Context->getDependentTemplateName(NNS,
(OverloadedOperatorKind)Record[Idx++]); (OverloadedOperatorKind)Record[Idx++]);
} }
case TemplateName::SubstTemplateTemplateParmPack: {
TemplateTemplateParmDecl *Param
= cast_or_null<TemplateTemplateParmDecl>(GetDecl(Record[Idx++]));
if (!Param)
return TemplateName();
TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx);
if (ArgPack.getKind() != TemplateArgument::Pack)
return TemplateName();
return Context->getSubstTemplateTemplateParmPack(Param, ArgPack);
}
} }
assert(0 && "Unhandled template name kind!"); assert(0 && "Unhandled template name kind!");
@ -4291,9 +4305,9 @@ ASTReader::ReadTemplateArgument(PerFileData &F,
return TemplateArgument(Value, T); return TemplateArgument(Value, T);
} }
case TemplateArgument::Template: case TemplateArgument::Template:
return TemplateArgument(ReadTemplateName(Record, Idx)); return TemplateArgument(ReadTemplateName(F, Record, Idx));
case TemplateArgument::TemplateExpansion: { case TemplateArgument::TemplateExpansion: {
TemplateName Name = ReadTemplateName(Record, Idx); TemplateName Name = ReadTemplateName(F, Record, Idx);
llvm::Optional<unsigned> NumTemplateExpansions; llvm::Optional<unsigned> NumTemplateExpansions;
if (unsigned NumExpansions = Record[Idx++]) if (unsigned NumExpansions = Record[Idx++])
NumTemplateExpansions = NumExpansions - 1; NumTemplateExpansions = NumExpansions - 1;

View File

@ -3214,6 +3214,14 @@ void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &Record) {
Record.push_back(DepT->getOperator()); Record.push_back(DepT->getOperator());
break; break;
} }
case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack();
AddDeclRef(SubstPack->getParameterPack(), Record);
AddTemplateArgument(SubstPack->getArgumentPack(), Record);
break;
}
} }
} }

View File

@ -149,4 +149,30 @@ namespace PacksAtDifferentLevels {
unsigned_pair<3, 4>, unsigned_pair<3, 4>,
unsigned_pair<5, 6>> unsigned_pair<5, 6>>
>::value == 0? 1 : -1]; >::value == 0? 1 : -1];
template<class> struct add_reference;
template<class> struct add_pointer;
template<class> struct add_const;
template<template<class> class ...Templates>
struct X5 {
template<typename> struct Inner {
static const unsigned value = 0;
};
template<typename ...Types>
struct Inner<tuple<Templates<Types>...>> {
static const unsigned value = 1;
};
};
int check10[X5<add_reference, add_pointer, add_const>
::Inner<tuple<add_reference<int>,
add_pointer<float>,
add_const<double>>>::value == 1? 1 : -1];
int check11[X5<add_reference, add_pointer>
::Inner<tuple<add_reference<int>,
add_pointer<float>,
add_const<double>>>::value == 0? 1 : -1];
} }

View File

@ -1228,6 +1228,11 @@ bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
return Visit(MakeCursorTemplateRef( return Visit(MakeCursorTemplateRef(
Name.getAsQualifiedTemplateName()->getDecl(), Name.getAsQualifiedTemplateName()->getDecl(),
Loc, TU)); Loc, TU));
case TemplateName::SubstTemplateTemplateParmPack:
return Visit(MakeCursorTemplateRef(
Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(),
Loc, TU));
} }
return false; return false;