xref: /llvm-project/clang/test/AST/ast-dump-ctad-alias.cpp (revision c7bfc41860a6abe5c92dc5afb47348b0c9e69963)
1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++2a -ast-dump %s | FileCheck -strict-whitespace %s
2 
3 template <typename, typename>
4 constexpr bool Concept = true;
5 template<typename T> // depth 0
6 struct Out {
7   template<typename U> // depth 1
8   struct Inner {
9     U t;
10   };
11 
12   template<typename V> // depth1
13   requires Concept<T, V>
14   Inner(V) -> Inner<V>;
15 };
16 
17 template <typename X>
18 struct Out2 {
19   template<typename Y> // depth1
20   using AInner = Out<int>::Inner<Y>;
21 };
22 Out2<double>::AInner t(1.0);
23 
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
28 //
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'
57 
58 // GH92596
59 template <typename T0>
60 struct Out3 {
61   template<class T1, typename T2>
62   struct Foo {
63     // Deduction guide:
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
67     Foo(V, T1);
68   };
69 };
70 template<class T3>
71 using AFoo3 = Out3<int>::Foo<T3, T3>;
72 AFoo3 afoo3{0, 1};
73 // Verify occurrence V in the require-clause is transformed (depth: 1 => 0, index: 2 => 1) correctly.
74 
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
84 
85 template <typename... T1>
86 struct Foo {
87   Foo(T1...);
88 };
89 
90 template <typename...T2>
91 using AFoo = Foo<T2...>;
92 AFoo a(1, 2);
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
96 
97 template <typename T>
98 using BFoo = Foo<T, T>;
99 BFoo b2(1.0, 2.0);
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
104 
105 namespace GH90209 {
106 // Case 1: type template parameter
107 template <class Ts>
108 struct List1 {
109   List1(int);
110 };
111 
112 template <class T1>
113 struct TemplatedClass1 {
114   TemplatedClass1(T1);
115 };
116 
117 template <class T1>
118 TemplatedClass1(T1) -> TemplatedClass1<List1<T1>>;
119 
120 template <class T2>
121 using ATemplatedClass1 = TemplatedClass1<List1<T2>>;
122 
123 ATemplatedClass1 test1(1);
124 // Verify that we have a correct template parameter list for the deduction guide.
125 //
126 // CHECK:      FunctionTemplateDecl {{.*}} <deduction guide for ATemplatedClass1>
127 // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T2
128 // CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible
129 
130 // Case 2: template template parameter
131 template<typename K> struct Foo{};
132 
133 template <template<typename> typename Ts>
134 struct List2 {
135   List2(int);
136 };
137 
138 template <typename T1>
139 struct TemplatedClass2 {
140   TemplatedClass2(T1);
141 };
142 
143 template <template<typename> typename T1>
144 TemplatedClass2(T1<int>) -> TemplatedClass2<List2<T1>>;
145 
146 template <template<typename> typename T2>
147 using ATemplatedClass2 = TemplatedClass2<List2<T2>>;
148 
149 List2<Foo> list(1);
150 ATemplatedClass2 test2(list);
151 // Verify that we have a correct template parameter list for the deduction guide.
152 //
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
157 
158 } // namespace GH90209
159