Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "[clang] Implement CWG2398 provisional TTP matching to class templates" #93258

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1807,8 +1807,6 @@ static void SetNestedNameSpecifier(Sema &S, TagDecl *T,
// Returns the template parameter list with all default template argument
// information.
static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
if (TD->isImplicit())
return TD->getTemplateParameters();
// Make sure we get the template parameter list from the most
// recent declaration, since that is the only one that is guaranteed to
// have all the default template argument information.
Expand All @@ -1829,8 +1827,7 @@ static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
// template <class = void> friend struct C;
// };
// template struct S<int>;
while ((D->isImplicit() ||
D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) &&
while (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None &&
D->getPreviousDecl())
D = D->getPreviousDecl();
return cast<TemplateDecl>(D)->getTemplateParameters();
Expand Down
76 changes: 30 additions & 46 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,8 @@ static NamedDecl *getTemplateParameterWithDefault(Sema &S, NamedDecl *A,
R->setDefaultArgument(
S.Context,
S.getTrivialTemplateArgumentLoc(Default, QualType(), SourceLocation()));
if (T->hasTypeConstraint()) {
auto *C = T->getTypeConstraint();
if (R->hasTypeConstraint()) {
auto *C = R->getTypeConstraint();
R->setTypeConstraint(C->getConceptReference(),
C->getImmediatelyDeclaredConstraint());
}
Expand Down Expand Up @@ -583,53 +583,37 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
return TemplateDeductionResult::Success;

auto NewDeduced = DeducedTemplateArgument(Arg);
// Provisional resolution for CWG2398: If Arg names a template
// specialization, then we deduce a synthesized template template parameter
// based on A, but using the TS's arguments as defaults.
if (DefaultArguments.size() != 0) {
// Provisional resolution for CWG2398: If Arg is also a template template
// param, and it names a template specialization, then we deduce a
// synthesized template template parameter based on A, but using the TS's
// arguments as defaults.
if (auto *TempArg = dyn_cast_or_null<TemplateTemplateParmDecl>(
Arg.getAsTemplateDecl())) {
assert(Arg.getKind() == TemplateName::Template);
TemplateDecl *TempArg = Arg.getAsTemplateDecl();
assert(!TempArg->isExpandedParameterPack());

TemplateParameterList *As = TempArg->getTemplateParameters();
assert(DefaultArguments.size() <= As->size());

SmallVector<NamedDecl *, 4> Params(As->size());
for (unsigned I = 0; I < DefaultArguments.size(); ++I)
Params[I] = getTemplateParameterWithDefault(S, As->getParam(I),
DefaultArguments[I]);
for (unsigned I = DefaultArguments.size(); I < As->size(); ++I)
Params[I] = As->getParam(I);
// FIXME: We could unique these, and also the parameters, but we don't
// expect programs to contain a large enough amount of these deductions
// for that to be worthwhile.
auto *TPL = TemplateParameterList::Create(
S.Context, SourceLocation(), SourceLocation(), Params,
SourceLocation(), As->getRequiresClause());

TemplateDecl *TD;
switch (TempArg->getKind()) {
case Decl::TemplateTemplateParm: {
auto *A = cast<TemplateTemplateParmDecl>(TempArg);
assert(!A->isExpandedParameterPack());
TD = TemplateTemplateParmDecl::Create(
S.Context, A->getDeclContext(), SourceLocation(), A->getDepth(),
A->getPosition(), A->isParameterPack(), A->getIdentifier(),
A->wasDeclaredWithTypename(), TPL);
break;
}
case Decl::ClassTemplate: {
auto *A = cast<ClassTemplateDecl>(TempArg);
auto *CT = ClassTemplateDecl::Create(S.Context, A->getDeclContext(),
SourceLocation(), A->getDeclName(),
TPL, A->getTemplatedDecl());
CT->setPreviousDecl(A);
TD = CT;
break;
}
default:
llvm_unreachable("Unexpected Template Kind");
if (DefaultArguments.size() != 0) {
assert(DefaultArguments.size() <= As->size());
SmallVector<NamedDecl *, 4> Params(As->size());
for (unsigned I = 0; I < DefaultArguments.size(); ++I)
Params[I] = getTemplateParameterWithDefault(S, As->getParam(I),
DefaultArguments[I]);
for (unsigned I = DefaultArguments.size(); I < As->size(); ++I)
Params[I] = As->getParam(I);
// FIXME: We could unique these, and also the parameters, but we don't
// expect programs to contain a large enough amount of these deductions
// for that to be worthwhile.
auto *TPL = TemplateParameterList::Create(
S.Context, SourceLocation(), SourceLocation(), Params,
SourceLocation(), As->getRequiresClause());
NewDeduced = DeducedTemplateArgument(
TemplateName(TemplateTemplateParmDecl::Create(
S.Context, TempArg->getDeclContext(), SourceLocation(),
TempArg->getDepth(), TempArg->getPosition(),
TempArg->isParameterPack(), TempArg->getIdentifier(),
TempArg->wasDeclaredWithTypename(), TPL)));
}
TD->setImplicit(true);
NewDeduced = DeducedTemplateArgument(TemplateName(TD));
}

DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Expand Down
5 changes: 2 additions & 3 deletions clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ namespace StdExample {
{ /* ... */ }

template<template<class> class TT>
void f(TT<int>);
void f(TT<int>); // expected-note {{candidate template ignored}}

template<template<class,class> class TT>
void g(TT<int, Alloc<int>>);

int h() {
f(v); // OK: TT = vector, Alloc<int> is used as the default argument for the
// second parameter.
f(v); // expected-error {{no matching function for call to 'f'}}
g(v); // OK: TT = vector
}

Expand Down
3 changes: 3 additions & 0 deletions clang/test/SemaTemplate/cwg2398.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,13 @@ namespace class_template {
template <class T3> struct B;

template <template <class T4> class TT1, class T5> struct B<TT1<T5>>;
// new-note@-1 {{partial specialization matches}}

template <class T6, class T7> struct B<A<T6, T7>> {};
// new-note@-1 {{partial specialization matches}}

template struct B<A<int>>;
// new-error@-1 {{ambiguous partial specialization}}
} // namespace class_template

namespace type_pack1 {
Expand Down
Loading