Skip to content

Commit 1abacfc

Browse files
committed
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. llvm-svn: 312049
1 parent c6daf73 commit 1abacfc

File tree

4 files changed

+34
-9
lines changed

4 files changed

+34
-9
lines changed

clang/include/clang/AST/TemplateName.h

+5
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ class TemplateName {
262262

263263
TemplateName getUnderlying() const;
264264

265+
/// Get the template name to substitute when this template name is used as a
266+
/// template template argument. This refers to the most recent declaration of
267+
/// the template, including any default template arguments.
268+
TemplateName getNameToSubstitute() const;
269+
265270
/// \brief Determines whether this is a dependent template name.
266271
bool isDependent() const;
267272

clang/lib/AST/TemplateName.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,23 @@ DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
131131
return Storage.dyn_cast<DependentTemplateName *>();
132132
}
133133

134+
TemplateName TemplateName::getNameToSubstitute() const {
135+
TemplateDecl *Decl = getAsTemplateDecl();
136+
137+
// Substituting a dependent template name: preserve it as written.
138+
if (!Decl)
139+
return *this;
140+
141+
// If we have a template declaration, use the most recent non-friend
142+
// declaration of that template.
143+
Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
144+
while (Decl->getFriendObjectKind()) {
145+
Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
146+
assert(Decl && "all declarations of template are friends");
147+
}
148+
return TemplateName(Decl);
149+
}
150+
134151
bool TemplateName::isDependent() const {
135152
if (TemplateDecl *Template = getAsTemplateDecl()) {
136153
if (isa<TemplateTemplateParmDecl>(Template))

clang/lib/Sema/SemaTemplateInstantiate.cpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
975975
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
976976
}
977977

978-
TemplateName Template = Arg.getAsTemplate();
978+
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
979979
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
980980
"Wrong kind of template template argument");
981981
return Template.getAsTemplateDecl();
@@ -1122,14 +1122,10 @@ TemplateName TemplateInstantiator::TransformTemplateName(
11221122
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
11231123
}
11241124

1125-
TemplateName Template = Arg.getAsTemplate();
1125+
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
11261126
assert(!Template.isNull() && "Null template template argument");
1127-
1128-
// We don't ever want to substitute for a qualified template name, since
1129-
// the qualifier is handled separately. So, look through the qualified
1130-
// template name to its underlying declaration.
1131-
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
1132-
Template = TemplateName(QTN->getTemplateDecl());
1127+
assert(!Template.getAsQualifiedTemplateName() &&
1128+
"template decl to substitute is qualified?");
11331129

11341130
Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template);
11351131
return Template;
@@ -1143,7 +1139,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(
11431139

11441140
TemplateArgument Arg = SubstPack->getArgumentPack();
11451141
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
1146-
return Arg.getAsTemplate();
1142+
return Arg.getAsTemplate().getNameToSubstitute();
11471143
}
11481144

11491145
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,

clang/test/SemaTemplate/temp_arg_template.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,10 @@ namespace PR32185 {
141141
template<template<typename T, T> class U> struct A {};
142142
template<template<typename T, T> class U> struct B : A<U> {};
143143
}
144+
145+
namespace PR10147 {
146+
template<typename T> struct A {};
147+
template<typename T = int> struct A;
148+
template<template<typename...> class A> void f(A<int>*) { A<> a; } // expected-warning 0-1{{extension}}
149+
void g() { f((A<>*)0); }
150+
}

0 commit comments

Comments
 (0)