1 | // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s |
2 | |
3 | template<class X, class Y, class Z> |
4 | class A {}; |
5 | template<class X> |
6 | class B {}; |
7 | template<class X> |
8 | class C {}; |
9 | |
10 | void foo_abbb(A<B<char>, B<char>, B<char> >) {} |
11 | // CHECK: "?foo_abbb@@YAXV?$A@V?$B@D@@V1@V1@@@@Z" |
12 | void foo_abb(A<char, B<char>, B<char> >) {} |
13 | // CHECK: "?foo_abb@@YAXV?$A@DV?$B@D@@V1@@@@Z" |
14 | void foo_abc(A<char, B<char>, C<char> >) {} |
15 | // CHECK: "?foo_abc@@YAXV?$A@DV?$B@D@@V?$C@D@@@@@Z" |
16 | void foo_bt(bool a, B<bool(bool)> b) {} |
17 | // CHECK: "?foo_bt@@YAX_NV?$B@$$A6A_N_N@Z@@@Z" |
18 | |
19 | namespace N { |
20 | template<class X, class Y, class Z> |
21 | class A {}; |
22 | template<class X> |
23 | class B {}; |
24 | template<class X> |
25 | class C {}; |
26 | template<class X, class Y> |
27 | class D {}; |
28 | class Z {}; |
29 | } |
30 | |
31 | void foo_abbb(N::A<N::B<char>, N::B<char>, N::B<char> >) {} |
32 | // CHECK: "?foo_abbb@@YAXV?$A@V?$B@D@N@@V12@V12@@N@@@Z" |
33 | void foo_abb(N::A<char, N::B<char>, N::B<char> >) {} |
34 | // CHECK: "?foo_abb@@YAXV?$A@DV?$B@D@N@@V12@@N@@@Z" |
35 | void foo_abc(N::A<char, N::B<char>, N::C<char> >) {} |
36 | // CHECK: "?foo_abc@@YAXV?$A@DV?$B@D@N@@V?$C@D@2@@N@@@Z" |
37 | |
38 | N::A<char, N::B<char>, N::C<char> > abc_foo() { |
39 | // CHECK: ?abc_foo@@YA?AV?$A@DV?$B@D@N@@V?$C@D@2@@N@@XZ |
40 | return N::A<char, N::B<char>, N::C<char> >(); |
41 | } |
42 | |
43 | N::Z z_foo(N::Z arg) { |
44 | // CHECK: ?z_foo@@YA?AVZ@N@@V12@@Z |
45 | return arg; |
46 | } |
47 | |
48 | N::B<char> b_foo(N::B<char> arg) { |
49 | // CHECK: ?b_foo@@YA?AV?$B@D@N@@V12@@Z |
50 | return arg; |
51 | } |
52 | |
53 | N::D<char, char> d_foo(N::D<char, char> arg) { |
54 | // CHECK: ?d_foo@@YA?AV?$D@DD@N@@V12@@Z |
55 | return arg; |
56 | } |
57 | |
58 | N::A<char, N::B<char>, N::C<char> > abc_foo_abc(N::A<char, N::B<char>, N::C<char> >) { |
59 | // CHECK: ?abc_foo_abc@@YA?AV?$A@DV?$B@D@N@@V?$C@D@2@@N@@V12@@Z |
60 | return N::A<char, N::B<char>, N::C<char> >(); |
61 | } |
62 | |
63 | namespace NA { |
64 | class X {}; |
65 | template<class T> class Y {}; |
66 | } |
67 | |
68 | namespace NB { |
69 | class X {}; |
70 | template<class T> class Y {}; |
71 | } |
72 | |
73 | void foo5(NA::Y<NB::Y<NA::Y<NB::Y<NA::X> > > > arg) {} |
74 | // CHECK: "?foo5@@YAXV?$Y@V?$Y@V?$Y@V?$Y@VX@NA@@@NB@@@NA@@@NB@@@NA@@@Z" |
75 | |
76 | void foo11(NA::Y<NA::X>, NB::Y<NA::X>) {} |
77 | // CHECK: "?foo11@@YAXV?$Y@VX@NA@@@NA@@V1NB@@@Z" |
78 | |
79 | void foo112(NA::Y<NA::X>, NB::Y<NB::X>) {} |
80 | // CHECK: "?foo112@@YAXV?$Y@VX@NA@@@NA@@V?$Y@VX@NB@@@NB@@@Z" |
81 | |
82 | void foo22(NA::Y<NB::Y<NA::X> >, NB::Y<NA::Y<NA::X> >) {} |
83 | // CHECK: "?foo22@@YAXV?$Y@V?$Y@VX@NA@@@NB@@@NA@@V?$Y@V?$Y@VX@NA@@@NA@@@NB@@@Z" |
84 | |
85 | namespace PR13207 { |
86 | class A {}; |
87 | class B {}; |
88 | class C {}; |
89 | |
90 | template<class X> |
91 | class F {}; |
92 | template<class X> |
93 | class I {}; |
94 | template<class X, class Y> |
95 | class J {}; |
96 | template<class X, class Y, class Z> |
97 | class K {}; |
98 | |
99 | class L { |
100 | public: |
101 | void foo(I<A> x) {} |
102 | }; |
103 | // CHECK: "?foo@L@PR13207@@QAEXV?$I@VA@PR13207@@@2@@Z" |
104 | |
105 | void call_l_foo(L* l) { l->foo(I<A>()); } |
106 | |
107 | void foo(I<A> x) {} |
108 | // CHECK: "?foo@PR13207@@YAXV?$I@VA@PR13207@@@1@@Z" |
109 | void foo2(I<A> x, I<A> y) { } |
110 | // CHECK: "?foo2@PR13207@@YAXV?$I@VA@PR13207@@@1@0@Z" |
111 | void bar(J<A,B> x) {} |
112 | // CHECK: "?bar@PR13207@@YAXV?$J@VA@PR13207@@VB@2@@1@@Z" |
113 | void spam(K<A,B,C> x) {} |
114 | // CHECK: "?spam@PR13207@@YAXV?$K@VA@PR13207@@VB@2@VC@2@@1@@Z" |
115 | |
116 | void baz(K<char, F<char>, I<char> >) {} |
117 | // CHECK: "?baz@PR13207@@YAXV?$K@DV?$F@D@PR13207@@V?$I@D@2@@1@@Z" |
118 | void qux(K<char, I<char>, I<char> >) {} |
119 | // CHECK: "?qux@PR13207@@YAXV?$K@DV?$I@D@PR13207@@V12@@1@@Z" |
120 | |
121 | namespace NA { |
122 | class X {}; |
123 | template<class T> class Y {}; |
124 | void foo(Y<X> x) {} |
125 | // CHECK: "?foo@NA@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z" |
126 | void foofoo(Y<Y<X> > x) {} |
127 | // CHECK: "?foofoo@NA@PR13207@@YAXV?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@12@@Z" |
128 | } |
129 | |
130 | namespace NB { |
131 | class X {}; |
132 | template<class T> class Y {}; |
133 | void foo(Y<NA::X> x) {} |
134 | // CHECK: "?foo@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z" |
135 | |
136 | void bar(NA::Y<X> x) {} |
137 | // CHECK: "?bar@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@NA@2@@Z" |
138 | |
139 | void spam(NA::Y<NA::X> x) {} |
140 | // CHECK: "?spam@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@NA@2@@Z" |
141 | |
142 | void foobar(NA::Y<Y<X> > a, Y<Y<X> >) {} |
143 | // CHECK: "?foobar@NB@PR13207@@YAXV?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V312@@Z" |
144 | |
145 | void foobarspam(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >) {} |
146 | // CHECK: "?foobarspam@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@@Z" |
147 | |
148 | void foobarbaz(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >, Y<Y<X> > c) {} |
149 | // CHECK: "?foobarbaz@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2@Z" |
150 | |
151 | void foobarbazqux(Y<X> a, NA::Y<Y<X> > b, Y<Y<X> >, Y<Y<X> > c , NA::Y<Y<Y<X> > > d) {} |
152 | // CHECK: "?foobarbazqux@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NA@2@V412@2V?$Y@V?$Y@V?$Y@VX@NB@PR13207@@@NB@PR13207@@@NB@PR13207@@@52@@Z" |
153 | } |
154 | |
155 | namespace NC { |
156 | class X {}; |
157 | template<class T> class Y {}; |
158 | |
159 | void foo(Y<NB::X> x) {} |
160 | // CHECK: "?foo@NC@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@@Z" |
161 | |
162 | void foobar(NC::Y<NB::Y<NA::Y<NA::X> > > x) {} |
163 | // CHECK: "?foobar@NC@PR13207@@YAXV?$Y@V?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@NB@PR13207@@@12@@Z" |
164 | } |
165 | } |
166 | |
167 | // Function template names are not considered for backreferencing, but normal |
168 | // function names are. |
169 | namespace fn_space { |
170 | struct RetVal { int hash; }; |
171 | template <typename T> |
172 | RetVal fun_tmpl(const T &t) { return RetVal(); } |
173 | RetVal fun_normal(int t) { return RetVal(); } |
174 | void fun_instantiate() { |
175 | fun_normal(1); |
176 | fun_tmpl(1); |
177 | } |
178 | // CHECK: "?fun_normal@fn_space@@YA?AURetVal@1@H@Z" |
179 | // CHECK: "??$fun_tmpl@H@fn_space@@YA?AURetVal@0@ABH@Z" |
180 | |
181 | template <typename T, RetVal (*F)(T)> |
182 | RetVal fun_tmpl_recurse(T t) { |
183 | if (!t) |
184 | return RetVal(); |
185 | return F(t - 1); |
186 | } |
187 | RetVal ident(int x) { return RetVal(); } |
188 | void fun_instantiate2() { |
189 | fun_tmpl_recurse<int, fun_tmpl_recurse<int, ident> >(10); |
190 | } |
191 | // CHECK: "??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z" |
192 | // CHECK: "??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z" |
193 | } |
194 | |