diff options
-rw-r--r-- | include/clang/AST/TemplateBase.h | 55 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 2 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 5 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 2 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 6 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 6 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp | 38 |
11 files changed, 117 insertions, 24 deletions
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 93ec35bebe..a4e074e083 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -80,8 +80,14 @@ private: const TemplateArgument *Args; unsigned NumArgs; } Args; + struct { + void *Name; + unsigned NumExpansions; + } TemplateArg; }; + TemplateArgument(TemplateName, bool); // DO NOT USE + public: /// \brief Construct an empty, invalid template argument. TemplateArgument() : Kind(Null), TypeOrValue(0) { } @@ -107,8 +113,7 @@ public: Integer.Type = Type.getAsOpaquePtr(); } - /// \brief Construct a template argument that is a template or a pack - /// expansion of templates. + /// \brief Construct a template argument that is a template. /// /// This form of template argument is generally used for template template /// parameters. However, the template name could be a dependent template @@ -116,13 +121,33 @@ public: /// is taken. /// /// \param Name The template name. - /// \param PackExpansion Whether this template argument is a pack expansion. - TemplateArgument(TemplateName Name, bool PackExpansion = false) - : Kind(PackExpansion? TemplateExpansion : Template) + TemplateArgument(TemplateName Name) : Kind(Template) { - TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer()); + TemplateArg.Name = Name.getAsVoidPointer(); + TemplateArg.NumExpansions = 0; } - + + /// \brief Construct a template argument that is a template pack expansion. + /// + /// This form of template argument is generally used for template template + /// parameters. However, the template name could be a dependent template + /// name that ends up being instantiated to a function template whose address + /// is taken. + /// + /// \param Name The template name. + /// + /// \param NumExpansions The number of expansions that will be generated by + /// instantiating + TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions) + : Kind(TemplateExpansion) + { + TemplateArg.Name = Name.getAsVoidPointer(); + if (NumExpansions) + TemplateArg.NumExpansions = *NumExpansions + 1; + else + TemplateArg.NumExpansions = 0; + } + /// \brief Construct a template argument that is an expression. /// /// This form of template argument only occurs in template argument @@ -151,6 +176,9 @@ public: } else if (Kind == Pack) { Args.NumArgs = Other.Args.NumArgs; Args.Args = Other.Args.Args; + } else if (Kind == Template || Kind == TemplateExpansion) { + TemplateArg.Name = Other.TemplateArg.Name; + TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; } else TypeOrValue = Other.TypeOrValue; } @@ -177,6 +205,9 @@ public: } else if (Other.Kind == Pack) { Args.NumArgs = Other.Args.NumArgs; Args.Args = Other.Args.Args; + } else if (Kind == Template || Kind == TemplateExpansion) { + TemplateArg.Name = Other.TemplateArg.Name; + TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; } else { TypeOrValue = Other.TypeOrValue; } @@ -234,8 +265,7 @@ public: if (Kind != Template) return TemplateName(); - return TemplateName::getFromVoidPointer( - reinterpret_cast<void*>(TypeOrValue)); + return TemplateName::getFromVoidPointer(TemplateArg.Name); } /// \brief Retrieve the template argument as a template name; if the argument @@ -244,10 +274,13 @@ public: if (Kind != Template && Kind != TemplateExpansion) return TemplateName(); - return TemplateName::getFromVoidPointer( - reinterpret_cast<void*>(TypeOrValue)); + return TemplateName::getFromVoidPointer(TemplateArg.Name); } + /// \brief Retrieve the number of expansions that a template template argument + /// expansion will produce, if known. + llvm::Optional<unsigned> getNumTemplateExpansions() const; + /// \brief Retrieve the template argument as an integral value. llvm::APSInt *getAsIntegral() { if (Kind != Integral) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a98e0636d4..e1e6fd08aa 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2768,7 +2768,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { case TemplateArgument::TemplateExpansion: return TemplateArgument(getCanonicalTemplateName( Arg.getAsTemplateOrTemplatePattern()), - true); + Arg.getNumTemplateExpansions()); case TemplateArgument::Integral: return TemplateArgument(*Arg.getAsIntegral(), diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 7989b9f278..f9fe18f5df 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1823,7 +1823,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { if (ToTemplate.isNull()) return TemplateArgument(); - return TemplateArgument(ToTemplate, true); + return TemplateArgument(ToTemplate, From.getNumTemplateExpansions()); } case TemplateArgument::Expression: diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index e7902e996a..b6716b34bd 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -337,7 +337,10 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { Arg = TemplateArgument(E); } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); - Arg = TemplateArgument(TemplateName(TTP), TTP->isParameterPack()); + if (TTP->isParameterPack()) + Arg = TemplateArgument(TemplateName(TTP), llvm::Optional<unsigned>()); + else + Arg = TemplateArgument(TemplateName(TTP)); } if ((*Param)->isTemplateParameterPack()) diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index 26c0c08971..f3def3eff2 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -135,6 +135,14 @@ bool TemplateArgument::containsUnexpandedParameterPack() const { return false; } +llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { + assert(Kind == TemplateExpansion); + if (TemplateArg.NumExpansions) + return TemplateArg.NumExpansions - 1; + + return llvm::Optional<unsigned>(); +} + void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const { ID.AddInteger(Kind); @@ -223,7 +231,7 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const { return cast<PackExpansionExpr>(getAsExpr())->getPattern(); case TemplateExpansion: - return TemplateArgument(getAsTemplateOrTemplatePattern(), false); + return TemplateArgument(getAsTemplateOrTemplatePattern()); case Declaration: case Integral: @@ -389,8 +397,8 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, } case TemplateArgument::TemplateExpansion: - // FIXME: Variadic templates num expansions Ellipsis = getTemplateEllipsisLoc(); + NumExpansions = Argument.getNumTemplateExpansions(); return TemplateArgumentLoc(Argument.getPackExpansionPattern(), getTemplateQualifierRange(), getTemplateNameLoc()); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5101b3b525..3c9d386f81 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -467,8 +467,12 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, case ParsedTemplateArgument::Template: { TemplateName Template = Arg.getAsTemplate().get(); - return TemplateArgumentLoc(TemplateArgument(Template, - Arg.getEllipsisLoc().isValid()), + TemplateArgument TArg; + if (Arg.getEllipsisLoc().isValid()) + TArg = TemplateArgument(Template, llvm::Optional<unsigned int>()); + else + TArg = Template; + return TemplateArgumentLoc(TArg, Arg.getScopeSpec().getRange(), Arg.getLocation(), Arg.getEllipsisLoc()); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 13cc17ef53..17b38bc1de 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -809,11 +809,8 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); - if (getSema().ArgumentPackSubstitutionIndex == -1) { - // FIXME: Variadic templates fun case. - getSema().Diag(Loc, diag::err_pack_expansion_mismatch_unsupported); + if (getSema().ArgumentPackSubstitutionIndex == -1) return 0; - } assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 4abcb88fc0..02c95bdb13 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2188,7 +2188,7 @@ public: case TemplateArgument::Template: return TemplateArgumentLoc(TemplateArgument( Pattern.getArgument().getAsTemplate(), - true), + NumExpansions), Pattern.getTemplateQualifierRange(), Pattern.getTemplateNameLoc(), EllipsisLoc); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 2c52f7f3a0..c6ecdea410 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4290,9 +4290,13 @@ ASTReader::ReadTemplateArgument(PerFileData &F, return TemplateArgument(Value, T); } case TemplateArgument::Template: + return TemplateArgument(ReadTemplateName(Record, Idx)); case TemplateArgument::TemplateExpansion: { TemplateName Name = ReadTemplateName(Record, Idx); - return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion); + llvm::Optional<unsigned> NumTemplateExpansions; + if (unsigned NumExpansions = Record[Idx++]) + NumTemplateExpansions = NumExpansions - 1; + return TemplateArgument(Name, NumTemplateExpansions); } case TemplateArgument::Expression: return TemplateArgument(ReadExpr(F)); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 00d46bc660..54a2648cd3 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3231,8 +3231,14 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg, AddTypeRef(Arg.getIntegralType(), Record); break; case TemplateArgument::Template: + AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record); + break; case TemplateArgument::TemplateExpansion: AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record); + if (llvm::Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions()) + Record.push_back(*NumExpansions + 1); + else + Record.push_back(0); break; case TemplateArgument::Expression: AddStmt(Arg.getAsExpr()); diff --git a/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp index 64554ab634..5ce5e63adb 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp @@ -88,4 +88,42 @@ namespace PacksAtDifferentLevels { pair<int, unsigned int>, pair<long, unsigned long>) >::value == 1? 1 : -1]; + + template<typename T, typename U> + struct some_function_object { + template<typename> + struct result_of; + }; + + template<template<class> class...> struct metafun_tuple { }; + + template<typename ...Types1> + struct X3 { + template<typename, typename> struct Inner { + static const unsigned value = 0; + }; + + template<typename ...Types2> + struct Inner<tuple<pair<Types1, Types2>...>, + metafun_tuple<some_function_object<Types1, Types2>::template result_of...> > { + static const unsigned value = 1; + }; + }; + + int check6[X3<short, int, long>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + metafun_tuple< + some_function_object<short, unsigned short>::result_of, + some_function_object<int, unsigned int>::result_of, + some_function_object<long, unsigned long>::result_of> + >::value == 1? 1 : -1]; + int check7[X3<short, int>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + metafun_tuple< + some_function_object<short, unsigned short>::result_of, + some_function_object<int, unsigned int>::result_of, + some_function_object<long, unsigned long>::result_of> + >::value == 0? 1 : -1]; } |