Replace the representation of template template argument pack

expansions with something that is easier to use correctly: a new
template argment kind, rather than a bit on an existing kind. Update
all of the switch statements that deal with template arguments, fixing
a few latent bugs in the process. I"m happy with this representation,
now.

And, oh look! Template instantiation and deduction work for template
template argument pack expansions.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122896 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2011-01-05 18:58:31 +00:00
Родитель cbf40f913a
Коммит a7fc901a2e
19 изменённых файлов: 243 добавлений и 88 удалений

Просмотреть файл

@ -535,7 +535,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
return getDerived().TraverseType(Arg.getAsType());
case TemplateArgument::Template:
return getDerived().TraverseTemplateName(Arg.getAsTemplate());
case TemplateArgument::TemplateExpansion:
return getDerived().TraverseTemplateName(
Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(Arg.getAsExpr());
@ -570,7 +572,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
}
case TemplateArgument::Template:
return getDerived().TraverseTemplateName(Arg.getAsTemplate());
case TemplateArgument::TemplateExpansion:
return getDerived().TraverseTemplateName(
Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(ArgLoc.getSourceExpression());

Просмотреть файл

@ -55,6 +55,9 @@ public:
/// The template argument is a template name that was provided for a
/// template template parameter.
Template,
/// The template argument is a pack expansion of a template name that was
/// provided for a template template parameter.
TemplateExpansion,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
Expression,
@ -77,10 +80,6 @@ private:
TemplateArgument *Args;
unsigned NumArgs;
} Args;
struct {
void *Template;
bool PackExpansion;
} TemplateArg;
};
public:
@ -119,10 +118,9 @@ public:
/// \param Name The template name.
/// \param PackExpansion Whether this template argument is a pack expansion.
TemplateArgument(TemplateName Name, bool PackExpansion = false)
: Kind(Template)
: Kind(PackExpansion? TemplateExpansion : Template)
{
TemplateArg.Template = Name.getAsVoidPointer();
TemplateArg.PackExpansion = PackExpansion;
TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
}
/// \brief Construct a template argument that is an expression.
@ -153,8 +151,6 @@ public:
} else if (Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
Args.Args = Other.Args.Args;
} else if (Kind == Template) {
TemplateArg = Other.TemplateArg;
} else
TypeOrValue = Other.TypeOrValue;
}
@ -181,8 +177,6 @@ public:
} else if (Other.Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
Args.Args = Other.Args.Args;
} else if (Other.Kind == Template) {
TemplateArg = Other.TemplateArg;
} else {
TypeOrValue = Other.TypeOrValue;
}
@ -234,9 +228,20 @@ public:
if (Kind != Template)
return TemplateName();
return TemplateName::getFromVoidPointer(TemplateArg.Template);
return TemplateName::getFromVoidPointer(
reinterpret_cast<void*>(TypeOrValue));
}
/// \brief Retrieve the template argument as a template name; if the argument
/// is a pack expansion, return the pattern as a template name.
TemplateName getAsTemplateOrTemplatePattern() const {
if (Kind != Template && Kind != TemplateExpansion)
return TemplateName();
return TemplateName::getFromVoidPointer(
reinterpret_cast<void*>(TypeOrValue));
}
/// \brief Retrieve the template argument as an integral value.
llvm::APSInt *getAsIntegral() {
if (Kind != Integral)
@ -394,12 +399,14 @@ public:
SourceLocation EllipsisLoc = SourceLocation())
: Argument(Argument),
LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) {
assert(Argument.getKind() == TemplateArgument::Template);
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
}
/// \brief - Fetches the primary location of the argument.
SourceLocation getLocation() const {
if (Argument.getKind() == TemplateArgument::Template)
if (Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion)
return getTemplateNameLoc();
return getSourceRange().getBegin();
@ -432,17 +439,19 @@ public:
}
SourceRange getTemplateQualifierRange() const {
assert(Argument.getKind() == TemplateArgument::Template);
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateQualifierRange();
}
SourceLocation getTemplateNameLoc() const {
assert(Argument.getKind() == TemplateArgument::Template);
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateNameLoc();
}
SourceLocation getTemplateEllipsisLoc() const {
assert(Argument.getKind() == TemplateArgument::Template);
assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateEllipsisLoc();
}

Просмотреть файл

@ -2692,7 +2692,12 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
case TemplateArgument::Template:
return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
case TemplateArgument::TemplateExpansion:
return TemplateArgument(getCanonicalTemplateName(
Arg.getAsTemplateOrTemplatePattern()),
true);
case TemplateArgument::Integral:
return TemplateArgument(*Arg.getAsIntegral(),
getCanonicalType(Arg.getIntegralType()));

Просмотреть файл

@ -301,7 +301,12 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return IsStructurallyEquivalent(Context,
Arg1.getAsTemplate(),
Arg2.getAsTemplate());
case TemplateArgument::TemplateExpansion:
return IsStructurallyEquivalent(Context,
Arg1.getAsTemplateOrTemplatePattern(),
Arg2.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return IsStructurallyEquivalent(Context,
Arg1.getAsExpr(), Arg2.getAsExpr());
@ -1785,7 +1790,16 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
return TemplateArgument(ToTemplate);
}
case TemplateArgument::TemplateExpansion: {
TemplateName ToTemplate
= Importer.Import(From.getAsTemplateOrTemplatePattern());
if (ToTemplate.isNull())
return TemplateArgument();
return TemplateArgument(ToTemplate, true);
}
case TemplateArgument::Expression:
if (Expr *ToExpr = Importer.Import(From.getAsExpr()))
return TemplateArgument(ToExpr);

Просмотреть файл

@ -179,7 +179,9 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
break;
case TemplateArgument::Template:
if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
case TemplateArgument::TemplateExpansion:
if (TemplateDecl *Template
= Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl())
LV = merge(LV, getLVForDecl(Template, F));
break;

Просмотреть файл

@ -319,6 +319,10 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
break;
}
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
// FIXME: Implement!
break;
case TemplateArgument::Declaration: {
visitDeclRef(A.getAsDecl());
break;

Просмотреть файл

@ -972,7 +972,8 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
break;
case TemplateArgument::Template:
VisitTemplateName(Arg.getAsTemplate());
case TemplateArgument::TemplateExpansion:
VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
break;
case TemplateArgument::Declaration:

Просмотреть файл

@ -39,7 +39,10 @@ bool TemplateArgument::isDependent() const {
case Template:
return getAsTemplate().isDependent();
case TemplateExpansion:
return true;
case Declaration:
if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
return DC->isDependentContext();
@ -70,14 +73,15 @@ bool TemplateArgument::isPackExpansion() const {
case Declaration:
case Integral:
case Pack:
case Template:
return false;
case TemplateExpansion:
return true;
case Type:
return isa<PackExpansionType>(getAsType());
case Template:
return TemplateArg.PackExpansion;
case Expression:
return isa<PackExpansionExpr>(getAsExpr());
}
@ -90,6 +94,7 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
case Null:
case Declaration:
case Integral:
case TemplateExpansion:
break;
case Type:
@ -98,8 +103,7 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
break;
case Template:
if (!TemplateArg.PackExpansion &&
getAsTemplate().containsUnexpandedParameterPack())
if (getAsTemplate().containsUnexpandedParameterPack())
return true;
break;
@ -135,20 +139,22 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
break;
case Template:
ID.AddBoolean(TemplateArg.PackExpansion);
case TemplateExpansion: {
TemplateName Template = getAsTemplateOrTemplatePattern();
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(
getAsTemplate().getAsTemplateDecl())) {
Template.getAsTemplateDecl())) {
ID.AddBoolean(true);
ID.AddInteger(TTP->getDepth());
ID.AddInteger(TTP->getPosition());
ID.AddBoolean(TTP->isParameterPack());
} else {
ID.AddBoolean(false);
ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
.getAsVoidPointer());
ID.AddPointer(Context.getCanonicalTemplateName(Template)
.getAsVoidPointer());
}
break;
}
case Integral:
getAsIntegral()->Profile(ID);
@ -173,13 +179,11 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
case Null:
case Type:
case Declaration:
case Expression:
case Expression:
case Template:
case TemplateExpansion:
return TypeOrValue == Other.TypeOrValue;
case Template:
return TemplateArg.Template == Other.TemplateArg.Template &&
TemplateArg.PackExpansion == Other.TemplateArg.PackExpansion;
case Integral:
return getIntegralType() == Other.getIntegralType() &&
*getAsIntegral() == *Other.getAsIntegral();
@ -206,13 +210,14 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
case Expression:
return cast<PackExpansionExpr>(getAsExpr())->getPattern();
case Template:
return TemplateArgument(getAsTemplate(), false);
case TemplateExpansion:
return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
case Declaration:
case Integral:
case Pack:
case Null:
case Template:
return TemplateArgument();
}
@ -248,13 +253,15 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
break;
}
case Template: {
case Template:
getAsTemplate().print(Out, Policy);
if (TemplateArg.PackExpansion)
Out << "...";
break;
}
case TemplateExpansion:
getAsTemplateOrTemplatePattern().print(Out, Policy);
Out << "...";
break;
case Integral: {
Out << getAsIntegral()->toString(10);
break;
@ -299,15 +306,18 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
else
return SourceRange();
case TemplateArgument::Template: {
SourceLocation End = getTemplateNameLoc();
if (getTemplateEllipsisLoc().isValid())
End = getTemplateEllipsisLoc();
case TemplateArgument::Template:
if (getTemplateQualifierRange().isValid())
return SourceRange(getTemplateQualifierRange().getBegin(), End);
return SourceRange(getTemplateNameLoc(), End);
}
return SourceRange(getTemplateQualifierRange().getBegin(),
getTemplateNameLoc());
return SourceRange(getTemplateNameLoc());
case TemplateArgument::TemplateExpansion:
if (getTemplateQualifierRange().isValid())
return SourceRange(getTemplateQualifierRange().getBegin(),
getTemplateEllipsisLoc());
return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
@ -355,13 +365,14 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
return TemplateArgumentLoc(Pattern, Pattern);
}
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
getTemplateQualifierRange(),
getTemplateNameLoc());
case TemplateArgument::Declaration:
case TemplateArgument::Template:
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
@ -389,11 +400,11 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
return DB << Arg.getAsIntegral()->toString(10);
case TemplateArgument::Template:
DB << Arg.getAsTemplate();
if (Arg.isPackExpansion())
DB << "...";
return DB;
return DB << Arg.getAsTemplate();
case TemplateArgument::TemplateExpansion:
return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
case TemplateArgument::Expression: {
// This shouldn't actually ever happen, so it's okay that we're
// regurgitating an expression here.

Просмотреть файл

@ -2169,6 +2169,11 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
// This is mangled as <type>.
mangleType(A.getAsTemplate());
break;
case TemplateArgument::TemplateExpansion:
// This is mangled as Dp <type>.
Out << "Dp";
mangleType(A.getAsTemplateOrTemplatePattern());
break;
case TemplateArgument::Expression:
Out << 'X';
mangleExpression(A.getAsExpr());

Просмотреть файл

@ -1693,11 +1693,12 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
break;
case TemplateArgument::Template: {
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
// [...] the namespaces in which any template template arguments are
// defined; and the classes in which any member templates used as
// template template arguments are defined.
TemplateName Template = Arg.getAsTemplate();
TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
if (ClassTemplateDecl *ClassTemplate
= dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
DeclContext *Ctx = ClassTemplate->getDeclContext();

Просмотреть файл

@ -2256,10 +2256,12 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
break;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
// We were given a template template argument. It may not be ill-formed;
// see below.
if (DependentTemplateName *DTN
= Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
= Arg.getArgument().getAsTemplateOrTemplatePattern()
.getAsDependentTemplateName()) {
// We have a template argument such as \c T::template X, which we
// parsed as a template template argument. However, since we now
// know that we need a non-type template argument, convert this
@ -2273,6 +2275,17 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
Arg.getTemplateQualifierRange(),
NameInfo);
// If we parsed the template argument as a pack expansion, create a
// pack expansion expression.
if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
ExprResult Expansion = ActOnPackExpansion(E,
Arg.getTemplateEllipsisLoc());
if (Expansion.isInvalid())
return true;
E = Expansion.get();
}
TemplateArgument Result;
if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
return true;
@ -2348,6 +2361,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return true;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
if (CheckTemplateArgument(TempParm, Arg))
return true;

Просмотреть файл

@ -168,7 +168,16 @@ checkDeducedTemplateArguments(ASTContext &Context,
// All other combinations are incompatible.
return DeducedTemplateArgument();
case TemplateArgument::TemplateExpansion:
if (Y.getKind() == TemplateArgument::TemplateExpansion &&
Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(),
Y.getAsTemplateOrTemplatePattern()))
return X;
// All other combinations are incompatible.
return DeducedTemplateArgument();
case TemplateArgument::Expression:
// If we deduced a dependent expression in one case and either an integral
// constant or a declaration in another case, keep the integral constant
@ -934,7 +943,7 @@ DeduceTemplateArguments(Sema &S,
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::Template:
if (Arg.getKind() == TemplateArgument::Template)
return DeduceTemplateArguments(S, TemplateParams,
@ -943,6 +952,10 @@ DeduceTemplateArguments(Sema &S,
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
case TemplateArgument::TemplateExpansion:
llvm_unreachable("caller should handle pack expansions");
break;
case TemplateArgument::Declaration:
if (Arg.getKind() == TemplateArgument::Declaration &&
@ -1282,10 +1295,11 @@ static bool isSameTemplateArg(ASTContext &Context,
Y.getAsDecl()->getCanonicalDecl();
case TemplateArgument::Template:
return Context.getCanonicalTemplateName(X.getAsTemplate())
.getAsVoidPointer() ==
Context.getCanonicalTemplateName(Y.getAsTemplate())
.getAsVoidPointer();
case TemplateArgument::TemplateExpansion:
return Context.getCanonicalTemplateName(
X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
Context.getCanonicalTemplateName(
Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
case TemplateArgument::Integral:
return *X.getAsIntegral() == *Y.getAsIntegral();
@ -1356,9 +1370,11 @@ getTrivialTemplateArgumentLoc(Sema &S,
}
case TemplateArgument::Template:
return TemplateArgumentLoc(Arg, SourceRange(), Loc,
Arg.isPackExpansion()? Loc : SourceLocation());
return TemplateArgumentLoc(Arg, SourceRange(), Loc);
case TemplateArgument::TemplateExpansion:
return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
case TemplateArgument::Expression:
return TemplateArgumentLoc(Arg, Arg.getAsExpr());
@ -3244,7 +3260,9 @@ MarkUsedTemplateParameters(Sema &SemaRef,
break;
case TemplateArgument::Template:
MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(),
case TemplateArgument::TemplateExpansion:
MarkUsedTemplateParameters(SemaRef,
TemplateArg.getAsTemplateOrTemplatePattern(),
OnlyDeduced, Depth, Used);
break;

Просмотреть файл

@ -2123,12 +2123,18 @@ public:
}
case TemplateArgument::Template:
llvm_unreachable("Unsupported pack expansion of templates");
return TemplateArgumentLoc(TemplateArgument(
Pattern.getArgument().getAsTemplate(),
true),
Pattern.getTemplateQualifierRange(),
Pattern.getTemplateNameLoc(),
EllipsisLoc);
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
case TemplateArgument::Pack:
case TemplateArgument::TemplateExpansion:
llvm_unreachable("Pack expansion pattern has no parameter packs");
case TemplateArgument::Type:
@ -2531,7 +2537,11 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
case TemplateArgument::Template:
Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
break;
case TemplateArgument::TemplateExpansion:
Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
break;
case TemplateArgument::Expression:
Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
break;
@ -2600,7 +2610,10 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
Input.getTemplateNameLoc());
return false;
}
case TemplateArgument::TemplateExpansion:
llvm_unreachable("Caller should expand pack expansions");
case TemplateArgument::Expression: {
// Template argument expressions are not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(getSema(),

Просмотреть файл

@ -3379,6 +3379,12 @@ ASTReader::GetTemplateArgumentLocInfo(PerFileData &F,
case TemplateArgument::Type:
return GetTypeSourceInfo(F, Record, Index);
case TemplateArgument::Template: {
SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
SourceLocation());
}
case TemplateArgument::TemplateExpansion: {
SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
@ -4216,7 +4222,8 @@ ASTReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
TemplateArgument
ASTReader::ReadTemplateArgument(PerFileData &F,
const RecordData &Record, unsigned &Idx) {
switch ((TemplateArgument::ArgKind)Record[Idx++]) {
TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
switch (Kind) {
case TemplateArgument::Null:
return TemplateArgument();
case TemplateArgument::Type:
@ -4228,10 +4235,10 @@ ASTReader::ReadTemplateArgument(PerFileData &F,
QualType T = GetType(Record[Idx++]);
return TemplateArgument(Value, T);
}
case TemplateArgument::Template: {
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
TemplateName Name = ReadTemplateName(Record, Idx);
bool IsPackExpansion = Record[Idx++];
return TemplateArgument(Name, IsPackExpansion);
return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion);
}
case TemplateArgument::Expression:
return TemplateArgument(ReadExpr(F));

Просмотреть файл

@ -2887,6 +2887,10 @@ void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record);
break;
case TemplateArgument::Template:
AddSourceRange(Arg.getTemplateQualifierRange(), Record);
AddSourceLocation(Arg.getTemplateNameLoc(), Record);
break;
case TemplateArgument::TemplateExpansion:
AddSourceRange(Arg.getTemplateQualifierRange(), Record);
AddSourceLocation(Arg.getTemplateNameLoc(), Record);
AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record);
@ -3176,8 +3180,8 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg,
AddTypeRef(Arg.getIntegralType(), Record);
break;
case TemplateArgument::Template:
AddTemplateName(Arg.getAsTemplate(), Record);
Record.push_back(Arg.isPackExpansion());
case TemplateArgument::TemplateExpansion:
AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
break;
case TemplateArgument::Expression:
AddStmt(Arg.getAsExpr());

Просмотреть файл

@ -163,4 +163,44 @@ namespace TemplateTemplateApply {
int check0[is_same<apply_each<int,
add_reference, add_pointer, add_const>::type,
tuple<int&, int*, int const>>::value? 1 : -1];
template<typename T, template<class> class ...Meta>
struct apply_each_indirect {
typedef typename apply_each<T, Meta...>::type type;
};
int check1[is_same<apply_each_indirect<int, add_reference, add_pointer,
add_const>::type,
tuple<int&, int*, int const>>::value? 1 : -1];
template<typename T, typename ...Meta>
struct apply_each_nested {
typedef typename apply_each<T, Meta::template apply...>::type type;
};
struct add_reference_meta {
template<typename T>
struct apply {
typedef T& type;
};
};
struct add_pointer_meta {
template<typename T>
struct apply {
typedef T* type;
};
};
struct add_const_meta {
template<typename T>
struct apply {
typedef const T type;
};
};
int check2[is_same<apply_each_nested<int, add_reference_meta,
add_pointer_meta, add_const_meta>::type,
tuple<int&, int*, int const>>::value? 1 : -1];
}

Просмотреть файл

@ -18,7 +18,7 @@ struct is_same<T, T> {
static const bool value = true;
};
// FIXME: Many more bullets to go
// FIXME: Several more bullets to go
// In an initializer-list (8.5); the pattern is an initializer-clause.
// Note: this also covers expression-lists, since expression-list is

Просмотреть файл

@ -1256,7 +1256,8 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
return false;
case TemplateArgument::Template:
return VisitTemplateName(TAL.getArgument().getAsTemplate(),
case TemplateArgument::TemplateExpansion:
return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
TAL.getTemplateNameLoc());
}

Просмотреть файл

@ -708,7 +708,9 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
break;
case TemplateArgument::Template:
VisitTemplateName(Arg.getAsTemplate());
case TemplateArgument::TemplateExpansion:
// FIXME: variadic templates
VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
break;
case TemplateArgument::Expression: