Author: rsmith Date: Tue Aug 29 15:14:43 2017 New Revision: 312049 URL: http://llvm.org/viewvc/llvm-project?rev=312049&view=rev Log: PR10147: When substituting a template template argument, substitute in the most recent (non-friend) declaration to pick up the right set of default template arguments.
Modified: cfe/trunk/include/clang/AST/TemplateName.h cfe/trunk/lib/AST/TemplateName.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp cfe/trunk/test/SemaTemplate/temp_arg_template.cpp Modified: cfe/trunk/include/clang/AST/TemplateName.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateName.h?rev=312049&r1=312048&r2=312049&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/TemplateName.h (original) +++ cfe/trunk/include/clang/AST/TemplateName.h Tue Aug 29 15:14:43 2017 @@ -262,6 +262,11 @@ public: TemplateName getUnderlying() const; + /// Get the template name to substitute when this template name is used as a + /// template template argument. This refers to the most recent declaration of + /// the template, including any default template arguments. + TemplateName getNameToSubstitute() const; + /// \brief Determines whether this is a dependent template name. bool isDependent() const; Modified: cfe/trunk/lib/AST/TemplateName.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateName.cpp?rev=312049&r1=312048&r2=312049&view=diff ============================================================================== --- cfe/trunk/lib/AST/TemplateName.cpp (original) +++ cfe/trunk/lib/AST/TemplateName.cpp Tue Aug 29 15:14:43 2017 @@ -131,6 +131,23 @@ DependentTemplateName *TemplateName::get return Storage.dyn_cast<DependentTemplateName *>(); } +TemplateName TemplateName::getNameToSubstitute() const { + TemplateDecl *Decl = getAsTemplateDecl(); + + // Substituting a dependent template name: preserve it as written. + if (!Decl) + return *this; + + // If we have a template declaration, use the most recent non-friend + // declaration of that template. + Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); + while (Decl->getFriendObjectKind()) { + Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); + assert(Decl && "all declarations of template are friends"); + } + return TemplateName(Decl); +} + bool TemplateName::isDependent() const { if (TemplateDecl *Template = getAsTemplateDecl()) { if (isa<TemplateTemplateParmDecl>(Template)) Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=312049&r1=312048&r2=312049&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Aug 29 15:14:43 2017 @@ -975,7 +975,7 @@ Decl *TemplateInstantiator::TransformDec Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } - TemplateName Template = Arg.getAsTemplate(); + TemplateName Template = Arg.getAsTemplate().getNameToSubstitute(); assert(!Template.isNull() && Template.getAsTemplateDecl() && "Wrong kind of template template argument"); return Template.getAsTemplateDecl(); @@ -1122,14 +1122,10 @@ TemplateName TemplateInstantiator::Trans Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } - TemplateName Template = Arg.getAsTemplate(); + TemplateName Template = Arg.getAsTemplate().getNameToSubstitute(); assert(!Template.isNull() && "Null template template argument"); - - // We don't ever want to substitute for a qualified template name, since - // the qualifier is handled separately. So, look through the qualified - // template name to its underlying declaration. - if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - Template = TemplateName(QTN->getTemplateDecl()); + assert(!Template.getAsQualifiedTemplateName() && + "template decl to substitute is qualified?"); Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template); return Template; @@ -1143,7 +1139,7 @@ TemplateName TemplateInstantiator::Trans TemplateArgument Arg = SubstPack->getArgumentPack(); Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); - return Arg.getAsTemplate(); + return Arg.getAsTemplate().getNameToSubstitute(); } return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, Modified: cfe/trunk/test/SemaTemplate/temp_arg_template.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_template.cpp?rev=312049&r1=312048&r2=312049&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/temp_arg_template.cpp (original) +++ cfe/trunk/test/SemaTemplate/temp_arg_template.cpp Tue Aug 29 15:14:43 2017 @@ -141,3 +141,10 @@ namespace PR32185 { template<template<typename T, T> class U> struct A {}; template<template<typename T, T> class U> struct B : A<U> {}; } + +namespace PR10147 { + template<typename T> struct A {}; + template<typename T = int> struct A; + template<template<typename...> class A> void f(A<int>*) { A<> a; } // expected-warning 0-1{{extension}} + void g() { f((A<>*)0); } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits