Skip to content

Commit ac81ad0

Browse files
author
git apple-llvm automerger
committed
Merge commit '040e7ad8281d' from llvm.org/main into next
2 parents 49b5144 + 040e7ad commit ac81ad0

File tree

3 files changed

+76
-10
lines changed

3 files changed

+76
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ Bug Fixes to C++ Support
875875
- Clang no longer crashes when trying to unify the types of arrays with
876876
certain differences in qualifiers (this could happen during template argument
877877
deduction or when building a ternary operator). (#GH97005)
878-
- Fixed type alias CTAD issues involving default template arguments. (#GH134471)
878+
- Fixed type alias CTAD issues involving default template arguments. (#GH133132), (#GH134471)
879879
- Fixed CTAD issues when initializing anonymous fields with designated initializers. (#GH67173)
880880
- The initialization kind of elements of structured bindings
881881
direct-list-initialized from an array is corrected to direct-initialization.

clang/lib/Sema/SemaTemplateDeductionGuide.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
949949
ReturnType = SemaRef.SubstType(
950950
ReturnType, Args, AliasTemplate->getLocation(),
951951
Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate));
952-
};
952+
}
953953

954954
SmallVector<TypeSourceInfo *> IsDeducibleTypeTraitArgs = {
955955
Context.getTrivialTypeSourceInfo(
@@ -981,7 +981,8 @@ getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) {
981981
// template<typename T>
982982
// using AliasFoo1 = Foo<T>; // a class/type alias template specialization
983983
Template = TST->getTemplateName().getAsTemplateDecl();
984-
AliasRhsTemplateArgs = TST->template_arguments();
984+
AliasRhsTemplateArgs =
985+
TST->getAsNonAliasTemplateSpecializationType()->template_arguments();
985986
} else if (const auto *RT = RhsType->getAs<RecordType>()) {
986987
// Cases where template arguments in the RHS of the alias are not
987988
// dependent. e.g.
@@ -1025,6 +1026,24 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
10251026
auto [Template, AliasRhsTemplateArgs] =
10261027
getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
10271028

1029+
// We need both types desugared, before we continue to perform type deduction.
1030+
// The intent is to get the template argument list 'matched', e.g. in the
1031+
// following case:
1032+
//
1033+
//
1034+
// template <class T>
1035+
// struct A {};
1036+
// template <class T>
1037+
// using Foo = A<A<T>>;
1038+
// template <class U = int>
1039+
// using Bar = Foo<U>;
1040+
//
1041+
// In terms of Bar, we want U (which has the default argument) to appear in
1042+
// the synthesized deduction guide, but U would remain undeduced if we deduced
1043+
// A<A<T>> using Foo<U> directly.
1044+
//
1045+
// Instead, we need to canonicalize both against A, i.e. A<A<T>> and A<A<U>>,
1046+
// such that T can be deduced as U.
10281047
auto RType = F->getTemplatedDecl()->getReturnType();
10291048
// The (trailing) return type of the deduction guide.
10301049
const TemplateSpecializationType *FReturnType =
@@ -1034,7 +1053,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
10341053
FReturnType = InjectedCNT->getInjectedTST();
10351054
else if (const auto *ET = RType->getAs<ElaboratedType>())
10361055
// explicit deduction guide.
1037-
FReturnType = ET->getNamedType()->getAs<TemplateSpecializationType>();
1056+
FReturnType = ET->getNamedType()->getAsNonAliasTemplateSpecializationType();
10381057
assert(FReturnType && "expected to see a return type");
10391058
// Deduce template arguments of the deduction guide f from the RHS of
10401059
// the alias.

clang/test/SemaCXX/cxx20-ctad-type-alias.cpp

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,14 @@ namespace test15 {
207207
template <class T> struct Foo { Foo(T); };
208208

209209
template<class V> using AFoo = Foo<V *>;
210-
template<typename> concept False = false;
210+
template<typename> concept False = false; // #test15_False
211211
template<False W>
212-
using BFoo = AFoo<W>; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \
213-
// expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo<int *>'}} \
214-
// 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 *>}} \
215-
// expected-note {{candidate template ignored: could not match 'Foo<V *>' against 'int *'}} \
216-
// expected-note {{template <class V> requires __is_deducible(AFoo, Foo<V *>) && __is_deducible(test15::BFoo, Foo<V *>) BFoo(Foo<V *>) -> Foo<V *>}}
212+
using BFoo = AFoo<W>; // expected-note {{candidate template ignored: constraints not satisfied [with W = int]}} \
213+
// expected-note@-1 {{because 'int' does not satisfy 'False'}} \
214+
// expected-note@#test15_False {{because 'false' evaluated to false}} \
215+
// 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 *>}} \
216+
// expected-note {{candidate template ignored: could not match 'Foo<W *>' against 'int *'}} \
217+
// expected-note {{template <False<> W> requires __is_deducible(AFoo, Foo<W *>) && __is_deducible(test15::BFoo, Foo<W *>) BFoo(Foo<W *>) -> Foo<W *>}}
217218
int i = 0;
218219
AFoo a1(&i); // OK, deduce Foo<int *>
219220

@@ -441,6 +442,32 @@ ACase4 case4{0, 1};
441442

442443
} // namespace test24
443444

445+
namespace test25 {
446+
447+
template<typename T, typename...Us>
448+
struct A{
449+
template<typename V> requires __is_same(V, int)
450+
A(V);
451+
};
452+
453+
template<typename...TS>
454+
using AA = A<int, TS...>;
455+
456+
template<typename...US>
457+
using BB = AA<US...>; // #test25_BB
458+
459+
BB a{0};
460+
static_assert(__is_same(decltype(a), A<int>));
461+
// FIXME: The template parameter list of generated deduction guide is not strictly conforming,
462+
// as the pack occurs prior to the non-packs.
463+
BB b{0, 1};
464+
// expected-error@-1 {{no viable}}
465+
// expected-note@#test25_BB 2{{not viable}}
466+
// expected-note@#test25_BB {{template <typename ...US, typename V> requires __is_same(V, int) && __is_deducible(AA, A<int, US...>) && __is_deducible(test25::BB, A<int, US...>) BB(V) -> A<int, US...>}}
467+
// expected-note@#test25_BB {{implicit deduction guide}}
468+
469+
}
470+
444471
namespace GH92212 {
445472
template<typename T, typename...Us>
446473
struct A{
@@ -526,6 +553,7 @@ void foo() { test<{1, 2, 3}>(); }
526553

527554
} // namespace GH113518
528555

556+
// FIXME: This is accepted by GCC: https://gcc.godbolt.org/z/f3rMfbacz
529557
namespace GH125821 {
530558
template<typename T>
531559
struct A { A(T){} };
@@ -539,3 +567,22 @@ using C = Proxy< A<T> >;
539567
C test{ 42 }; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
540568

541569
} // namespace GH125821
570+
571+
namespace GH133132 {
572+
573+
template <class T>
574+
struct A {};
575+
576+
template <class T>
577+
using Foo = A<A<T>>;
578+
579+
template <class T>
580+
using Bar = Foo<T>;
581+
582+
template <class T = int>
583+
using Baz = Bar<T>;
584+
585+
Baz a{};
586+
static_assert(__is_same(decltype(a), A<A<int>>));
587+
588+
} // namespace GH133132

0 commit comments

Comments
 (0)