mirror of https://github.com/microsoft/clang.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@312049 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d1cb214fe8
commit
bfd88732fe
|
@ -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;
|
||||
|
||||
|
|
|
@ -131,6 +131,23 @@ DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
|
|||
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))
|
||||
|
|
|
@ -975,7 +975,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
|
|||
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::TransformTemplateName(
|
|||
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::TransformTemplateName(
|
|||
|
||||
TemplateArgument Arg = SubstPack->getArgumentPack();
|
||||
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
||||
return Arg.getAsTemplate();
|
||||
return Arg.getAsTemplate().getNameToSubstitute();
|
||||
}
|
||||
|
||||
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
|
||||
|
|
|
@ -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); }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue