diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 894ecdd29a..7e39a344a6 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -535,7 +535,9 @@ bool RecursiveASTVisitor::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::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()); diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 758926c957..7f3e591a96 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -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(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(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(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(); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b4520609ff..6e7f7c31ea 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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())); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 70c8632047..5a94de9020 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -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); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 08272e76ca..5b82ddd7c6 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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; diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp index 7465ea410d..65a18aa8d1 100644 --- a/lib/AST/DumpXML.cpp +++ b/lib/AST/DumpXML.cpp @@ -319,6 +319,10 @@ struct XMLDumper : public XMLDeclVisitor, break; } case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + // FIXME: Implement! + break; + case TemplateArgument::Declaration: { visitDeclRef(A.getAsDecl()); break; diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 17a9326cc0..63c3197ebc 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -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: diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index 6eae6a4192..de5531f0f7 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -39,7 +39,10 @@ bool TemplateArgument::isDependent() const { case Template: return getAsTemplate().isDependent(); - + + case TemplateExpansion: + return true; + case Declaration: if (DeclContext *DC = dyn_cast(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(getAsType()); - - case Template: - return TemplateArg.PackExpansion; - + case Expression: return isa(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( - 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(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(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. diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 0969b8716f..ff0e9223c8 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -2169,6 +2169,11 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P, // This is mangled as . mangleType(A.getAsTemplate()); break; + case TemplateArgument::TemplateExpansion: + // This is mangled as Dp . + Out << "Dp"; + mangleType(A.getAsTemplateOrTemplatePattern()); + break; case TemplateArgument::Expression: Out << 'X'; mangleExpression(A.getAsExpr()); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 5ed973b1a8..161908e200 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -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(Template.getAsTemplateDecl())) { DeclContext *Ctx = ClassTemplate->getDeclContext(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 9adcf1c81f..2c9a4307ed 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index a72a29378a..5837ebd8e5 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -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; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 919f2c879c..d15f91a745 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -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::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::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(), diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index ed0e58f18f..3bf51e6a0e 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -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)); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 44f17e40b1..2c0239de17 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -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()); diff --git a/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp b/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp index 3e9e8f5fb2..75181081ad 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp @@ -163,4 +163,44 @@ namespace TemplateTemplateApply { int check0[is_same::type, tuple>::value? 1 : -1]; + + template class ...Meta> + struct apply_each_indirect { + typedef typename apply_each::type type; + }; + + int check1[is_same::type, + tuple>::value? 1 : -1]; + + template + struct apply_each_nested { + typedef typename apply_each::type type; + }; + + struct add_reference_meta { + template + struct apply { + typedef T& type; + }; + }; + + struct add_pointer_meta { + template + struct apply { + typedef T* type; + }; + }; + + struct add_const_meta { + template + struct apply { + typedef const T type; + }; + }; + + int check2[is_same::type, + tuple>::value? 1 : -1]; + } diff --git a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp index 7e6a6b0f0d..b865d51411 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -18,7 +18,7 @@ struct is_same { 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 diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index f28115418b..979d678d5a 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -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()); } diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index c96dad5cd0..8aed372be6 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -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: