Daniel Dunbar | a572887 | 2009-12-15 20:14:24 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
Douglas Gregor | d85bea2 | 2009-09-26 06:47:28 +0000 | [diff] [blame] | 2 | // PR5057 |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 3 | namespace test0 { |
| 4 | namespace std { |
| 5 | class X { |
| 6 | public: |
| 7 | template<typename T> friend struct Y; |
| 8 | }; |
| 9 | } |
| 10 | |
| 11 | namespace std { |
| 12 | template<typename T> struct Y {}; |
| 13 | } |
Douglas Gregor | d85bea2 | 2009-09-26 06:47:28 +0000 | [diff] [blame] | 14 | } |
| 15 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 16 | namespace test1 { |
Douglas Gregor | 182ddf0 | 2009-09-28 00:08:27 +0000 | [diff] [blame] | 17 | template<typename T> void f1(T) { } // expected-note{{here}} |
| 18 | |
| 19 | class X { |
| 20 | template<typename T> friend void f0(T); |
| 21 | template<typename T> friend void f1(T); |
| 22 | }; |
| 23 | |
| 24 | template<typename T> void f0(T) { } |
| 25 | template<typename T> void f1(T) { } // expected-error{{redefinition}} |
| 26 | } |
Douglas Gregor | d7e5bdb | 2009-10-09 21:11:42 +0000 | [diff] [blame] | 27 | |
| 28 | // PR4768 |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 29 | namespace test2 { |
| 30 | template<typename T> struct X0 { |
| 31 | template<typename U> friend struct X0; |
| 32 | }; |
| 33 | |
| 34 | template<typename T> struct X0<T*> { |
| 35 | template<typename U> friend struct X0; |
| 36 | }; |
Douglas Gregor | d7e5bdb | 2009-10-09 21:11:42 +0000 | [diff] [blame] | 37 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 38 | template<> struct X0<int> { |
| 39 | template<typename U> friend struct X0; |
| 40 | }; |
Douglas Gregor | d7e5bdb | 2009-10-09 21:11:42 +0000 | [diff] [blame] | 41 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 42 | template<typename T> struct X1 { |
| 43 | template<typename U> friend void f2(U); |
| 44 | template<typename U> friend void f3(U); |
| 45 | }; |
Douglas Gregor | a735b20 | 2009-10-13 14:39:41 +0000 | [diff] [blame] | 46 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 47 | template<typename U> void f2(U); |
Douglas Gregor | a735b20 | 2009-10-13 14:39:41 +0000 | [diff] [blame] | 48 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 49 | X1<int> x1i; |
| 50 | X0<int*> x0ip; |
Douglas Gregor | a735b20 | 2009-10-13 14:39:41 +0000 | [diff] [blame] | 51 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 52 | template<> void f2(int); |
Douglas Gregor | a735b20 | 2009-10-13 14:39:41 +0000 | [diff] [blame] | 53 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 54 | // FIXME: Should this declaration of f3 be required for the specialization of |
| 55 | // f3<int> (further below) to work? GCC and EDG don't require it, we do... |
| 56 | template<typename U> void f3(U); |
Douglas Gregor | a735b20 | 2009-10-13 14:39:41 +0000 | [diff] [blame] | 57 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 58 | template<> void f3(int); |
| 59 | } |
Douglas Gregor | e8c01bd | 2009-10-30 21:07:27 +0000 | [diff] [blame] | 60 | |
| 61 | // PR5332 |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 62 | namespace test3 { |
| 63 | template <typename T> class Foo { |
| 64 | template <typename U> |
| 65 | friend class Foo; |
| 66 | }; |
Douglas Gregor | e8c01bd | 2009-10-30 21:07:27 +0000 | [diff] [blame] | 67 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 68 | Foo<int> foo; |
Douglas Gregor | 259571e | 2009-10-30 22:42:42 +0000 | [diff] [blame] | 69 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 70 | template<typename T, T Value> struct X2a; |
Douglas Gregor | 259571e | 2009-10-30 22:42:42 +0000 | [diff] [blame] | 71 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 72 | template<typename T, int Size> struct X2b; |
Douglas Gregor | 259571e | 2009-10-30 22:42:42 +0000 | [diff] [blame] | 73 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 74 | template<typename T> |
| 75 | class X3 { |
| 76 | template<typename U, U Value> friend struct X2a; |
John McCall | 93ba857 | 2010-03-25 06:39:04 +0000 | [diff] [blame] | 77 | |
| 78 | // FIXME: the redeclaration note ends up here because redeclaration |
| 79 | // lookup ends up finding the friend target from X3<int>. |
| 80 | template<typename U, T Value> friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}} \ |
| 81 | // expected-note {{previous non-type template parameter with type 'int' is here}} |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 82 | }; |
Douglas Gregor | 259571e | 2009-10-30 22:42:42 +0000 | [diff] [blame] | 83 | |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 84 | X3<int> x3i; // okay |
Douglas Gregor | 259571e | 2009-10-30 22:42:42 +0000 | [diff] [blame] | 85 | |
John McCall | 93ba857 | 2010-03-25 06:39:04 +0000 | [diff] [blame] | 86 | X3<long> x3l; // expected-note {{in instantiation}} |
John McCall | 4b6e90a | 2009-12-11 20:51:23 +0000 | [diff] [blame] | 87 | } |
John McCall | e976ffe | 2009-12-14 23:19:40 +0000 | [diff] [blame] | 88 | |
| 89 | // PR5716 |
| 90 | namespace test4 { |
| 91 | template<typename> struct A { |
| 92 | template<typename T> friend void f(const A<T>&); |
| 93 | }; |
| 94 | |
| 95 | template<typename T> void f(const A<T>&) { |
Chandler Carruth | b2b5cc0 | 2011-01-04 04:44:35 +0000 | [diff] [blame] | 96 | int a[sizeof(T) ? -1 : -1]; // expected-error {{array with a negative size}} |
John McCall | e976ffe | 2009-12-14 23:19:40 +0000 | [diff] [blame] | 97 | } |
| 98 | |
| 99 | void f() { |
| 100 | f(A<int>()); // expected-note {{in instantiation of function template specialization}} |
| 101 | } |
| 102 | } |
John McCall | 65c4946 | 2009-12-18 11:25:59 +0000 | [diff] [blame] | 103 | |
| 104 | namespace test5 { |
| 105 | class outer { |
| 106 | class foo; |
| 107 | template <typename T> friend struct cache; |
| 108 | }; |
| 109 | class outer::foo { |
| 110 | template <typename T> friend struct cache; |
| 111 | }; |
| 112 | } |
Douglas Gregor | 5d52e47 | 2010-01-16 18:09:52 +0000 | [diff] [blame] | 113 | |
| 114 | // PR6022 |
| 115 | namespace PR6022 { |
| 116 | template <class T1, class T2 , class T3 > class A; |
| 117 | |
| 118 | namespace inner { |
| 119 | template<class T1, class T2, class T3, class T> |
| 120 | A<T1, T2, T3>& f0(A<T1, T2, T3>&, T); |
| 121 | } |
| 122 | |
| 123 | template<class T1, class T2, class T3> |
| 124 | class A { |
| 125 | template<class U1, class U2, class U3, class T> |
| 126 | friend A<U1, U2, U3>& inner::f0(A<U1, U2, U3>&, T); |
| 127 | }; |
| 128 | } |
| 129 | |
Douglas Gregor | d4598a2 | 2010-04-28 04:52:24 +0000 | [diff] [blame] | 130 | namespace FriendTemplateDefinition { |
| 131 | template<unsigned > struct int_c { }; |
| 132 | |
| 133 | template<typename T> |
| 134 | struct X { |
| 135 | template<unsigned N> |
| 136 | friend void f(X, int_c<N>) { |
| 137 | int value = N; |
| 138 | }; |
| 139 | }; |
| 140 | |
| 141 | void test_X(X<int> x, int_c<5> i5) { |
| 142 | f(x, i5); |
| 143 | } |
| 144 | } |
Douglas Gregor | e7089b0 | 2010-05-03 23:29:10 +0000 | [diff] [blame] | 145 | |
| 146 | namespace PR7013a { |
| 147 | template<class > struct X0 |
| 148 | { |
| 149 | typedef int type; |
| 150 | }; |
| 151 | template<typename > struct X1 |
| 152 | { |
| 153 | }; |
| 154 | template<typename , typename T> struct X2 |
| 155 | { |
| 156 | typename T::type e; |
| 157 | }; |
| 158 | namespace N |
| 159 | { |
| 160 | template <typename = int, typename = X1<int> > struct X3 |
| 161 | { |
| 162 | template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B); |
| 163 | }; |
| 164 | template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B) |
| 165 | { |
| 166 | X2<int, Tr> s; |
| 167 | } |
| 168 | } |
| 169 | int n() |
| 170 | { |
| 171 | X2<int, X0<int> > ngs; |
| 172 | N::X3<> b; |
| 173 | op(ngs, b); |
| 174 | return 0; |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | namespace PR7013b { |
| 179 | template<class > struct X0 |
| 180 | { |
| 181 | typedef int type; |
| 182 | }; |
| 183 | template<typename > struct X1 |
| 184 | { |
| 185 | }; |
| 186 | template<typename , typename T> struct X2 |
| 187 | { |
| 188 | typename T::type e; |
| 189 | }; |
| 190 | namespace N |
| 191 | { |
| 192 | template <typename = X1<int> > struct X3 |
| 193 | { |
| 194 | template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B); |
| 195 | }; |
| 196 | template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B) |
| 197 | { |
| 198 | X2<int, Tr> s; |
| 199 | } |
| 200 | } |
| 201 | int n() |
| 202 | { |
| 203 | X2<int, X0<int> > ngs; |
| 204 | N::X3<> b; |
| 205 | op(ngs, b); |
| 206 | return 0; |
| 207 | } |
| 208 | |
| 209 | } |
Douglas Gregor | b0ee93c | 2010-12-21 08:14:57 +0000 | [diff] [blame] | 210 | |
| 211 | namespace PR8649 { |
| 212 | template<typename T, typename U, unsigned N> |
| 213 | struct X { |
| 214 | template<unsigned M> friend class X<T, U, M>; // expected-error{{partial specialization cannot be declared as a friend}} |
| 215 | }; |
| 216 | |
| 217 | X<int, float, 7> x; |
| 218 | } |
Chandler Carruth | 0f4be74 | 2011-05-03 18:35:10 +0000 | [diff] [blame] | 219 | |
| 220 | // Don't crash, and error on invalid friend type template. |
| 221 | namespace friend_type_template_no_tag { |
| 222 | template <typename T> struct S { |
| 223 | template <typename U> friend S<U>; // expected-error{{friend type templates must use an elaborated type}} |
| 224 | }; |
| 225 | template struct S<int>; |
| 226 | } |
Douglas Gregor | ba4ee9a | 2011-10-20 15:58:54 +0000 | [diff] [blame] | 227 | |
| 228 | namespace PR10660 { |
| 229 | struct A { |
| 230 | template <> friend class B; // expected-error{{extraneous 'template<>' in declaration of class 'B'}} |
| 231 | }; |
| 232 | } |
Douglas Gregor | 8b0fa52 | 2012-03-30 16:20:47 +0000 | [diff] [blame] | 233 | |
| 234 | namespace rdar11147355 { |
| 235 | template <class T> |
| 236 | struct A { |
| 237 | template <class U> class B; |
| 238 | template <class S> template <class U> friend class A<S>::B; |
| 239 | }; |
| 240 | |
| 241 | template <class S> template <class U> class A<S>::B { |
| 242 | }; |
| 243 | |
| 244 | A<double>::B<double> ab; |
| 245 | } |
Richard Smith | c93e014 | 2012-04-20 07:12:26 +0000 | [diff] [blame] | 246 | |
| 247 | namespace RedeclUnrelated { |
| 248 | struct S { |
| 249 | int packaged_task; |
| 250 | template<typename> class future { |
| 251 | template<typename> friend class packaged_task; |
| 252 | }; |
| 253 | future<void> share; |
| 254 | }; |
| 255 | } |
| 256 | |
| 257 | namespace PR12557 { |
| 258 | template <typename> |
| 259 | struct Foo; |
| 260 | |
| 261 | template <typename Foo_> |
| 262 | struct Bar { |
| 263 | typedef Foo_ Foo; // expected-note {{previous}} |
| 264 | |
| 265 | template <typename> friend struct Foo; // expected-error {{redefinition of 'Foo' as different kind of symbol}} |
| 266 | }; |
| 267 | |
| 268 | Bar<int> b; |
| 269 | } |
Richard Smith | 6e21b16 | 2012-04-22 02:13:50 +0000 | [diff] [blame] | 270 | |
| 271 | namespace PR12585 { |
| 272 | struct A { }; |
| 273 | template<typename> struct B { |
| 274 | template<typename> friend class A::does_not_exist; // \ |
| 275 | // expected-error {{friend declaration of 'does_not_exist' does not match any declaration in 'PR12585::A'}} |
| 276 | }; |
| 277 | |
| 278 | struct C { |
| 279 | template<typename> struct D; |
| 280 | }; |
| 281 | template<typename> class E { |
| 282 | int n; |
| 283 | template<typename> friend struct C::D; |
| 284 | }; |
| 285 | template<typename T> struct C::D { |
| 286 | int f() { |
| 287 | return E<int>().n; |
| 288 | } |
| 289 | }; |
| 290 | int n = C::D<void*>().f(); |
| 291 | |
| 292 | struct F { |
| 293 | template<int> struct G; |
| 294 | }; |
| 295 | template<typename T> struct H { |
| 296 | // FIXME: As with cases above, the note here is on an unhelpful declaration, |
| 297 | // and should point to the declaration of G within F. |
| 298 | template<T> friend struct F::G; // \ |
| 299 | // expected-error {{different type 'char' in template redeclaration}} \ |
| 300 | // expected-note {{previous}} |
| 301 | }; |
| 302 | H<int> h1; // ok |
| 303 | H<char> h2; // expected-note {{instantiation}} |
| 304 | } |