diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 39e9dbed0c3e0..268f079980a6c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1807,6 +1807,8 @@ 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. @@ -1827,7 +1829,8 @@ static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) { // template friend struct C; // }; // template struct S; - while (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None && + while ((D->isImplicit() || + D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) && D->getPreviousDecl()) D = D->getPreviousDecl(); return cast(D)->getTemplateParameters(); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index f16a07e1a1b34..76f47e9cb2560 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -527,8 +527,8 @@ static NamedDecl *getTemplateParameterWithDefault(Sema &S, NamedDecl *A, R->setDefaultArgument( S.Context, S.getTrivialTemplateArgumentLoc(Default, QualType(), SourceLocation())); - if (R->hasTypeConstraint()) { - auto *C = R->getTypeConstraint(); + if (T->hasTypeConstraint()) { + auto *C = T->getTypeConstraint(); R->setTypeConstraint(C->getConceptReference(), C->getImmediatelyDeclaredConstraint()); } @@ -583,37 +583,53 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, return TemplateDeductionResult::Success; auto NewDeduced = DeducedTemplateArgument(Arg); - // 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( - Arg.getAsTemplateDecl())) { + // 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) { assert(Arg.getKind() == TemplateName::Template); - assert(!TempArg->isExpandedParameterPack()); - + TemplateDecl *TempArg = Arg.getAsTemplateDecl(); TemplateParameterList *As = TempArg->getTemplateParameters(); - if (DefaultArguments.size() != 0) { - assert(DefaultArguments.size() <= As->size()); - SmallVector 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))); + assert(DefaultArguments.size() <= As->size()); + + SmallVector 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(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(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"); } + TD->setImplicit(true); + NewDeduced = DeducedTemplateArgument(TemplateName(TD)); } DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp index a5b39fe5c51f7..bc39431253880 100644 --- a/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp @@ -28,13 +28,14 @@ namespace StdExample { { /* ... */ } template class TT> - void f(TT); // expected-note {{candidate template ignored}} + void f(TT); template class TT> void g(TT>); int h() { - f(v); // expected-error {{no matching function for call to 'f'}} + f(v); // OK: TT = vector, Alloc is used as the default argument for the + // second parameter. g(v); // OK: TT = vector } diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp index e3b5e575374d3..4cc946735a1e2 100644 --- a/clang/test/SemaTemplate/cwg2398.cpp +++ b/clang/test/SemaTemplate/cwg2398.cpp @@ -65,13 +65,10 @@ namespace class_template { template struct B; template