llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Younan Zhang (zyn0217) <details> <summary>Changes</summary> We copy arguments from different template parameter lists depending on the deducibility of the template parameters. In particular, we may lose the default template argument from the original alias declaration, and this patch helps preserve that. Fixes https://github.com/llvm/llvm-project/issues/133132 --- Full diff: https://github.com/llvm/llvm-project/pull/147675.diff 3 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+1-1) - (modified) clang/lib/Sema/SemaTemplateDeductionGuide.cpp (+25-4) - (modified) clang/test/SemaCXX/cxx20-ctad-type-alias.cpp (+27-6) ``````````diff 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<DeducedTemplateArgument> 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 <class T> + // using Foo = A<A<T>>; + // + // template <class U = int> + // using Bar = Foo<U>; + // + // In terms of Bar, we want U to appear in the synthesized deduction guide, + // but U would remain undeduced if we deduce against A<T> 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<TemplateArgument> Ps = FReturnType->template_arguments(); + if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(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<TemplateArgument> DeducedArgs; SmallVector<unsigned> 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 <class T> struct Foo { Foo(T); }; template<class V> using AFoo = Foo<V *>; -template<typename> concept False = false; +template<typename> concept False = false; // #test15_False template<False W> -using BFoo = AFoo<W>; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ - // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo<int *>'}} \ - // expected-note {{implicit deduction guide declared as 'template <class V> requires __is_deducible(AFoo, Foo<V *>) && __is_deducible(test15::BFoo, Foo<V *>) BFoo(V *) -> Foo<V *>}} \ - // expected-note {{candidate template ignored: could not match 'Foo<V *>' against 'int *'}} \ - // expected-note {{template <class V> requires __is_deducible(AFoo, Foo<V *>) && __is_deducible(test15::BFoo, Foo<V *>) BFoo(Foo<V *>) -> Foo<V *>}} +using BFoo = AFoo<W>; // 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 <False<> W> requires __is_deducible(AFoo, Foo<W *>) && __is_deducible(test15::BFoo, Foo<W *>) BFoo(W *) -> Foo<W *>}} \ + // expected-note {{candidate template ignored: could not match 'Foo<W *>' against 'int *'}} \ + // expected-note {{template <False<> W> requires __is_deducible(AFoo, Foo<W *>) && __is_deducible(test15::BFoo, Foo<W *>) BFoo(Foo<W *>) -> Foo<W *>}} int i = 0; AFoo a1(&i); // OK, deduce Foo<int *> @@ -539,3 +540,23 @@ using C = Proxy< A<T> >; C test{ 42 }; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} } // namespace GH125821 + +namespace GH133132 { + +template <class T> +struct A {}; + +template <class T> +using Foo = A<A<T>>; + +template <class T = int> +using Bar = Foo<T>; + +template <class T = int, class U = int> +using Baz = Bar<T>; + +Bar a{}; + +Baz b{}; + +} // namespace GH133132 `````````` </details> https://github.com/llvm/llvm-project/pull/147675 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits