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 
foo_abbb(A<B<char>,B<char>,B<char>>)10 void foo_abbb(A<B<char>, B<char>, B<char> >) {}
11 // CHECK: "?foo_abbb@@YAXV?$A@V?$B@D@@V1@V1@@@@Z"
foo_abb(A<char,B<char>,B<char>>)12 void foo_abb(A<char, B<char>, B<char> >) {}
13 // CHECK: "?foo_abb@@YAXV?$A@DV?$B@D@@V1@@@@Z"
foo_abc(A<char,B<char>,C<char>>)14 void foo_abc(A<char, B<char>, C<char> >) {}
15 // CHECK: "?foo_abc@@YAXV?$A@DV?$B@D@@V?$C@D@@@@@Z"
foo_bt(bool a,B<bool (bool)> b)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 
foo_abbb(N::A<N::B<char>,N::B<char>,N::B<char>>)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"
foo_abb(N::A<char,N::B<char>,N::B<char>>)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"
foo_abc(N::A<char,N::B<char>,N::C<char>>)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 
abc_foo()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 
z_foo(N::Z arg)43 N::Z z_foo(N::Z arg) {
44 // CHECK: ?z_foo@@YA?AVZ@N@@V12@@Z
45   return arg;
46 }
47 
b_foo(N::B<char> arg)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 
d_foo(N::D<char,char> arg)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 
abc_foo_abc(N::A<char,N::B<char>,N::C<char>>)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 
foo5(NA::Y<NB::Y<NA::Y<NB::Y<NA::X>>>> arg)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 
foo11(NA::Y<NA::X>,NB::Y<NA::X>)76 void foo11(NA::Y<NA::X>, NB::Y<NA::X>) {}
77 // CHECK: "?foo11@@YAXV?$Y@VX@NA@@@NA@@V1NB@@@Z"
78 
foo112(NA::Y<NA::X>,NB::Y<NB::X>)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 
foo22(NA::Y<NB::Y<NA::X>>,NB::Y<NA::Y<NA::X>>)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:
foo(I<A> x)101   void foo(I<A> x) {}
102 };
103 // CHECK: "?foo@L@PR13207@@QAEXV?$I@VA@PR13207@@@2@@Z"
104 
call_l_foo(L * l)105 void call_l_foo(L* l) { l->foo(I<A>()); }
106 
foo(I<A> x)107 void foo(I<A> x) {}
108 // CHECK: "?foo@PR13207@@YAXV?$I@VA@PR13207@@@1@@Z"
foo2(I<A> x,I<A> y)109 void foo2(I<A> x, I<A> y) { }
110 // CHECK: "?foo2@PR13207@@YAXV?$I@VA@PR13207@@@1@0@Z"
bar(J<A,B> x)111 void bar(J<A,B> x) {}
112 // CHECK: "?bar@PR13207@@YAXV?$J@VA@PR13207@@VB@2@@1@@Z"
spam(K<A,B,C> x)113 void spam(K<A,B,C> x) {}
114 // CHECK: "?spam@PR13207@@YAXV?$K@VA@PR13207@@VB@2@VC@2@@1@@Z"
115 
baz(K<char,F<char>,I<char>>)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"
qux(K<char,I<char>,I<char>>)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 {};
foo(Y<X> x)124 void foo(Y<X> x) {}
125 // CHECK: "?foo@NA@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
foofoo(Y<Y<X>> x)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 {};
foo(Y<NA::X> x)133 void foo(Y<NA::X> x) {}
134 // CHECK: "?foo@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@12@@Z"
135 
bar(NA::Y<X> x)136 void bar(NA::Y<X> x) {}
137 // CHECK: "?bar@NB@PR13207@@YAXV?$Y@VX@NB@PR13207@@@NA@2@@Z"
138 
spam(NA::Y<NA::X> x)139 void spam(NA::Y<NA::X> x) {}
140 // CHECK: "?spam@NB@PR13207@@YAXV?$Y@VX@NA@PR13207@@@NA@2@@Z"
141 
foobar(NA::Y<Y<X>> a,Y<Y<X>>)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 
foobarspam(Y<X> a,NA::Y<Y<X>> b,Y<Y<X>>)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 
foobarbaz(Y<X> a,NA::Y<Y<X>> b,Y<Y<X>>,Y<Y<X>> c)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 
foobarbazqux(Y<X> a,NA::Y<Y<X>> b,Y<Y<X>>,Y<Y<X>> c,NA::Y<Y<Y<X>>> d)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 
foo(Y<NB::X> x)159 void foo(Y<NB::X> x) {}
160 // CHECK: "?foo@NC@PR13207@@YAXV?$Y@VX@NB@PR13207@@@12@@Z"
161 
foobar(NC::Y<NB::Y<NA::Y<NA::X>>> x)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>
fun_tmpl(const T & t)172 RetVal fun_tmpl(const T &t) { return RetVal(); }
fun_normal(int t)173 RetVal fun_normal(int t) { return RetVal(); }
fun_instantiate()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)>
fun_tmpl_recurse(T t)182 RetVal fun_tmpl_recurse(T t) {
183   if (!t)
184     return RetVal();
185   return F(t - 1);
186 }
ident(int x)187 RetVal ident(int x) { return RetVal(); }
fun_instantiate2()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