зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
cbf40f913a
Коммит
a7fc901a2e
|
@ -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:
|
||||
|
|
Загрузка…
Ссылка в новой задаче