1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++2a -ast-dump %s | FileCheck -strict-whitespace %s
3 template <typename
, typename
>
4 constexpr bool Concept
= true;
5 template<typename T
> // depth 0
7 template<typename U
> // depth 1
12 template<typename V
> // depth1
13 requires Concept
<T
, V
>
19 template<typename Y
> // depth1
20 using AInner
= Out
<int>::Inner
<Y
>;
22 Out2
<double>::AInner
t(1.0);
24 // Verify that the require-clause of alias deduction guide is transformed correctly:
25 // - Occurrence T should be replaced with `int`;
26 // - Occurrence V should be replaced with the Y with depth 1
27 // - Depth of occurrence Y in the __is_deducible constraint should be 1
29 // CHECK: | `-FunctionTemplateDecl {{.*}} <deduction guide for AInner>
30 // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 Y
31 // CHECK-NEXT: | |-BinaryOperator {{.*}} '<dependent type>' '&&'
32 // CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '<dependent type>' lvalue (no ADL) = 'Concept'
33 // CHECK-NEXT: | | | |-TemplateArgument type 'int'
34 // CHECK-NEXT: | | | | `-BuiltinType {{.*}} 'int'
35 // CHECK-NEXT: | | | `-TemplateArgument type 'Y':'type-parameter-1-0'
36 // CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0
37 // CHECK-NEXT: | | | `-TemplateTypeParm {{.*}} 'Y'
38 // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible
39 // CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2<double>::AInner' dependent
40 // CHECK-NEXT: | | | `-name: 'Out2<double>::AInner'
41 // CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}}
42 // CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner<Y>' sugar dependent
43 // CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner<Y>' dependent
44 // CHECK-NEXT: | | |-name: 'Inner':'Out<int>::Inner' qualified
45 // CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}}
46 // CHECK-NEXT: | | `-TemplateArgument type 'Y'
47 // CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'Y'
48 // CHECK-NEXT: | | |-FunctionTemplate {{.*}} '<deduction guide for Inner>'
49 // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0
50 // CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'Y'
51 // CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} <deduction guide for AInner> 'auto (Y) -> Inner<Y>'
52 // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'Y'
53 // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} used <deduction guide for AInner> 'auto (double) -> Inner<double>' implicit_instantiation
54 // CHECK-NEXT: | |-TemplateArgument type 'double'
55 // CHECK-NEXT: | | `-BuiltinType {{.*}} 'double'
56 // CHECK-NEXT: | `-ParmVarDecl {{.*}} 'double'
59 template <typename T0
>
61 template<class T1
, typename T2
>
64 // template <typename T1, typename T2, typename V>
65 // Foo(V, T1) -> Foo<T1, T2>;
66 template<class V
> requires Concept
<T0
, V
> // V in require clause of Foo deduction guide: depth 1, index: 2
71 using AFoo3
= Out3
<int>::Foo
<T3
, T3
>;
73 // Verify occurrence V in the require-clause is transformed (depth: 1 => 0, index: 2 => 1) correctly.
75 // CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for AFoo3>
76 // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T3
77 // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 1 V
78 // CHECK-NEXT: |-BinaryOperator {{.*}} '<dependent type>' '&&'
79 // CHECK-NEXT: | |-UnresolvedLookupExpr {{.*}} '<dependent type>' lvalue (no ADL) = 'Concept'
80 // CHECK-NEXT: | | |-TemplateArgument type 'int'
81 // CHECK-NEXT: | | | `-BuiltinType {{.*}} 'int'
82 // CHECK-NEXT: | | `-TemplateArgument type 'V'
83 // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'V' dependent depth 0 index 1
85 template <typename
... T1
>
90 template <typename
...T2
>
91 using AFoo
= Foo
<T2
...>;
93 // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for AFoo> 'auto (T2...) -> Foo<T2...>'
94 // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'T2...' pack
95 // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for AFoo> 'auto (int, int) -> Foo<int, int>' implicit_instantiation
98 using BFoo
= Foo
<T
, T
>;
100 // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for BFoo> 'auto (T, T) -> Foo<T, T>'
101 // CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'T'
102 // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'T'
103 // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for BFoo> 'auto (double, double) -> Foo<double, double>' implicit_instantiation
106 // Case 1: type template parameter
113 struct TemplatedClass1
{
118 TemplatedClass1(T1
) -> TemplatedClass1
<List1
<T1
>>;
121 using ATemplatedClass1
= TemplatedClass1
<List1
<T2
>>;
123 ATemplatedClass1
test1(1);
124 // Verify that we have a correct template parameter list for the deduction guide.
126 // CHECK: FunctionTemplateDecl {{.*}} <deduction guide for ATemplatedClass1>
127 // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T2
128 // CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible
130 // Case 2: template template parameter
131 template<typename K
> struct Foo
{};
133 template <template<typename
> typename Ts
>
138 template <typename T1
>
139 struct TemplatedClass2
{
143 template <template<typename
> typename T1
>
144 TemplatedClass2(T1
<int>) -> TemplatedClass2
<List2
<T1
>>;
146 template <template<typename
> typename T2
>
147 using ATemplatedClass2
= TemplatedClass2
<List2
<T2
>>;
150 ATemplatedClass2
test2(list
);
151 // Verify that we have a correct template parameter list for the deduction guide.
153 // CHECK: FunctionTemplateDecl {{.*}} <deduction guide for ATemplatedClass2>
154 // CHECK-NEXT: |-TemplateTemplateParmDecl {{.*}} depth 0 index 0 T2
155 // CHECK-NEXT: | `-TemplateTypeParmDecl {{.*}} typename depth 0 index 0
156 // CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible
158 } // namespace GH90209