diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 96477ef6ddc9a..2562650fcc622 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -803,7 +803,7 @@ Bug Fixes to C++ Support - Clang no longer crashes when trying to unify the types of arrays with certain differences in qualifiers (this could happen during template argument deduction or when building a ternary operator). (#GH97005) -- Fixed type alias CTAD issues involving default template arguments. (#GH134471) +- Fixed type alias CTAD issues involving default template arguments. (#GH133132), (#GH134471) - Fixed CTAD issues when initializing anonymous fields with designated initializers. (#GH67173) - The initialization kind of elements of structured bindings direct-list-initialized from an array is corrected to direct-initialization. diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index bdc46a0115a45..9eea2cc1dad4a 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -1061,15 +1061,36 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, SmallVector DeduceResults( F->getTemplateParameters()->size()); + // We don't have to deduce against the alias template specialization, + // if the source template is a synthesized alias deduction guide. This allows + // us to utilize the default template arguments from alias declaration. + // + // template + // using Foo = A>; + // + // template + // using Bar = Foo; + // + // In terms of Bar, we want U to appear in the synthesized deduction guide, + // but U would remain undeduced if we deduce against A instead of T. + // Also note that since the deduced results are only used for synthesizing + // template parameters, they should not introduce unintended behavior in + // theory. + ArrayRef Ps = FReturnType->template_arguments(); + if (auto *DG = dyn_cast(F->getTemplatedDecl()); + DG && DG->getSourceDeductionGuideKind() == + CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias) + Ps = F->getInjectedTemplateArgs(Context); + // FIXME: DeduceTemplateArguments stops immediately at the first // non-deducible template argument. However, this doesn't seem to cause // issues for practice cases, we probably need to extend it to continue // performing deduction for rest of arguments to align with the C++ // standard. - SemaRef.DeduceTemplateArguments( - F->getTemplateParameters(), FReturnType->template_arguments(), - AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, - /*NumberOfArgumentsMustMatch=*/false); + SemaRef.DeduceTemplateArguments(F->getTemplateParameters(), Ps, + AliasRhsTemplateArgs, TDeduceInfo, + DeduceResults, + /*NumberOfArgumentsMustMatch=*/false); SmallVector DeducedArgs; SmallVector NonDeducedTemplateParamsInFIndex; diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index aeb02c9e4898e..6d027130ce741 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -207,13 +207,14 @@ namespace test15 { template struct Foo { Foo(T); }; template using AFoo = Foo; -template concept False = false; +template concept False = false; // #test15_False template -using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ - // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo'}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(AFoo, Foo) && __is_deducible(test15::BFoo, Foo) BFoo(V *) -> Foo}} \ - // expected-note {{candidate template ignored: could not match 'Foo' against 'int *'}} \ - // expected-note {{template requires __is_deducible(AFoo, Foo) && __is_deducible(test15::BFoo, Foo) BFoo(Foo) -> Foo}} +using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with W = int]}} \ + // expected-note@-1 {{because 'int' does not satisfy 'False'}} \ + // expected-note@#test15_False {{because 'false' evaluated to false}} \ + // expected-note {{implicit deduction guide declared as 'template W> requires __is_deducible(AFoo, Foo) && __is_deducible(test15::BFoo, Foo) BFoo(W *) -> Foo}} \ + // expected-note {{candidate template ignored: could not match 'Foo' against 'int *'}} \ + // expected-note {{template W> requires __is_deducible(AFoo, Foo) && __is_deducible(test15::BFoo, Foo) BFoo(Foo) -> Foo}} int i = 0; AFoo a1(&i); // OK, deduce Foo @@ -539,3 +540,23 @@ using C = Proxy< A >; C test{ 42 }; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} } // namespace GH125821 + +namespace GH133132 { + +template +struct A {}; + +template +using Foo = A>; + +template +using Bar = Foo; + +template +using Baz = Bar; + +Bar a{}; + +Baz b{}; + +} // namespace GH133132