1// RUN: %clang_cc1 -verify -emit-llvm-only %s
2
3namespace test0 {
4template <typename T> struct Num {
5  T value_;
6
7public:
8  Num(T value) : value_(value) {}
9  T get() const { return value_; }
10
11  template <typename U> struct Rep {
12    U count_;
13    Rep(U count) : count_(count) {}
14
15    friend Num operator*(const Num &a, const Rep &n) {
16      Num x = 0;
17      for (U count = n.count_; count; --count)
18        x += a;
19      return x;
20    }
21  };
22
23  friend Num operator+(const Num &a, const Num &b) {
24    return a.value_ + b.value_;
25  }
26
27  Num& operator+=(const Num& b) {
28    value_ += b.value_;
29    return *this;
30  }
31
32  class Representation {};
33  friend class Representation;
34};
35
36class A {
37  template <typename T> friend bool iszero(const A &a) throw();
38};
39
40template <class T> class B_iterator;
41template <class T> class B {
42  friend class B_iterator<T>;
43};
44
45int calc1() {
46  Num<int> left = -1;
47  Num<int> right = 1;
48  Num<int> result = left + right;
49  return result.get();
50}
51
52int calc2() {
53  Num<int> x = 3;
54  Num<int>::Rep<char> n = (char) 10;
55  Num<int> result = x * n;
56  return result.get();
57}
58}
59
60// Reduced from GNU <locale>
61namespace test1 {
62  class A {
63    bool b; // expected-note {{declared private here}}
64    template <typename T> friend bool has(const A&);
65  };
66  template <typename T> bool has(const A &x) {
67    return x.b;
68  }
69  template <typename T> bool hasnot(const A &x) {
70    return x.b; // expected-error {{'b' is a private member of 'test1::A'}}
71  }
72}
73
74namespace test2 {
75  class A {
76    bool b; // expected-note {{declared private here}}
77    template <typename T> friend class HasChecker;
78  };
79  template <typename T> class HasChecker {
80    bool check(A *a) {
81      return a->b;
82    }
83  };
84  template <typename T> class HasNotChecker {
85    bool check(A *a) {
86      return a->b; // expected-error {{'b' is a private member of 'test2::A'}}
87    }
88  };
89}
90
91namespace test3 {
92  class Bool;
93  template <class T> class User;
94  template <class T> T transform(class Bool, T);
95
96  class Bool {
97    friend class User<bool>;
98    friend bool transform<>(Bool, bool);
99
100    bool value; // expected-note 2 {{declared private here}}
101  };
102
103  template <class T> class User {
104    static T compute(Bool b) {
105      return b.value; // expected-error {{'value' is a private member of 'test3::Bool'}}
106    }
107  };
108
109  template <class T> T transform(Bool b, T value) {
110    if (b.value) // expected-error {{'value' is a private member of 'test3::Bool'}}
111      return value;
112    return value + 1;
113  }
114
115  template bool transform(Bool, bool);
116  template int transform(Bool, int); // expected-note {{requested here}}
117
118  template class User<bool>;
119  template class User<int>; // expected-note {{requested here}}
120}
121
122namespace test4 {
123  template <class T> class A {
124    template <class T0> friend class B;
125    bool foo(const A<T> *) const;
126  };
127
128  template <class T> class B {
129    bool bar(const A<T> *a, const A<T> *b) {
130      return a->foo(b);
131    }
132  };
133
134  template class B<int>;
135}
136
137namespace test5 {
138  template <class T, class U=int> class A {};
139  template <class T> class B {
140    template <class X, class Y> friend class A;
141  };
142  template class B<int>;
143  template class A<int>;
144}
145
146namespace Dependent {
147  template<typename T, typename Traits> class X;
148  template<typename T, typename Traits>
149  X<T, Traits> operator+(const X<T, Traits>&, const T*);
150
151  template<typename T, typename Traits> class X {
152    typedef typename Traits::value_type value_type;
153    friend X operator+<>(const X&, const value_type*);
154  };
155}
156
157namespace test7 {
158  template <class T> class A { // expected-note {{declared here}}
159    friend class B;
160    int x; // expected-note {{declared private here}}
161  };
162
163  class B {
164    int foo(A<int> &a) {
165      return a.x;
166    }
167  };
168
169  class C {
170    int foo(A<int> &a) {
171      return a.x; // expected-error {{'x' is a private member of 'test7::A<int>'}}
172    }
173  };
174
175  // This shouldn't crash.
176  template <class T> class D {
177    friend class A; // expected-error {{elaborated type refers to a template}}
178  };
179  template class D<int>;
180}
181
182namespace test8 {
183  template <class N> class A {
184    static int x;
185    template <class T> friend void foo();
186  };
187  template class A<int>;
188
189  template <class T> void foo() {
190    A<int>::x = 0;
191  }
192  template void foo<int>();
193}
194
195namespace test9 {
196  template <class T> class A {
197    class B; class C;
198
199    int foo(B *b) {
200      return b->x;
201    }
202
203    int foo(C *c) {
204      return c->x; // expected-error {{'x' is a private member}}
205    }
206
207    class B {
208      int x;
209      friend int A::foo(B*);
210    };
211
212    class C {
213      int x; // expected-note {{declared private here}}
214    };
215  };
216
217  template class A<int>; // expected-note {{in instantiation}}
218}
219
220namespace test10 {
221  template <class T> class A;
222  template <class T> A<T> bar(const T*, const A<T>&);
223  template <class T> class A {
224  private:
225    void foo(); // expected-note {{declared private here}}
226    friend A bar<>(const T*, const A<T>&);
227  };
228
229  template <class T> A<T> bar(const T *l, const A<T> &r) {
230    A<T> l1;
231    l1.foo();
232
233    A<char> l2;
234    l2.foo(); // expected-error {{'foo' is a private member of 'test10::A<char>'}}
235
236    return l1;
237  }
238
239  template A<int> bar<int>(const int *, const A<int> &); // expected-note {{in instantiation}}
240}
241
242// PR6752: this shouldn't crash.
243namespace test11 {
244  struct Foo {
245    template<class A>
246    struct IteratorImpl {
247      template<class T> friend class IteratorImpl;
248    };
249  };
250
251  template struct Foo::IteratorImpl<int>;
252  template struct Foo::IteratorImpl<long>;
253}
254
255// PR6827
256namespace test12 {
257  template <typename T> class Foo;
258  template <typename T> Foo<T> foo(T* t){ return Foo<T>(t, true); }
259
260  template <typename T> class Foo {
261  public:
262    Foo(T*);
263    friend Foo<T> foo<T>(T*);
264  private:
265    Foo(T*, bool); // expected-note {{declared private here}}
266  };
267
268  // Should work.
269  int globalInt;
270  Foo<int> f = foo(&globalInt);
271
272  // Shouldn't work.
273  long globalLong;
274  template <> Foo<long> foo(long *t) {
275    Foo<int> s(&globalInt, false); // expected-error {{calling a private constructor}}
276    return Foo<long>(t, true);
277  }
278}
279
280// PR6514
281namespace test13 {
282  template <int N, template <int> class Temp>
283  class Role : public Temp<N> {
284    friend class Temp<N>;
285    int x;
286  };
287
288  template <int N> class Foo {
289    void foo(Role<N, test13::Foo> &role) {
290      (void) role.x;
291    }
292  };
293
294  template class Foo<0>;
295}
296
297namespace test14 {
298  template <class T> class B;
299  template <class T> class A {
300    friend void B<T>::foo();
301    static void foo(); // expected-note {{declared private here}}
302  };
303
304  template <class T> class B {
305  public:
306    void foo() { return A<long>::foo(); } // expected-error {{'foo' is a private member of 'test14::A<long>'}}
307  };
308
309  template class B<int>; // expected-note {{in instantiation}}
310}
311
312namespace test15 {
313  template <class T> class B;
314  template <class T> class A {
315    friend void B<T>::foo();
316
317    // This shouldn't be misrecognized as a templated-scoped reference.
318    template <class U> friend void B<T>::bar(U);
319
320    static void foo(); // expected-note {{declared private here}}
321  };
322
323  template <class T> class B {
324  public:
325    void foo() { return A<long>::foo(); } // expected-error {{'foo' is a private member of 'test15::A<long>'}}
326  };
327
328  template <> class B<float> {
329  public:
330    void foo() { return A<float>::foo(); }
331    template <class U> void bar(U u) {
332      (void) A<float>::foo();
333    }
334  };
335
336  template class B<int>; // expected-note {{in instantiation}}
337}
338
339namespace PR10913 {
340  template<class T> class X;
341
342  template<class T> void f(X<T> *x) {
343    x->member = 0;
344  }
345
346  template<class U, class T> void f2(X<T> *x) {
347    x->member = 0; // expected-error{{'member' is a protected member of 'PR10913::X<int>'}}
348  }
349
350  template<class T> class X {
351    friend void f<T>(X<T> *x);
352    friend void f2<T>(X<int> *x);
353
354  protected:
355    int member; // expected-note{{declared protected here}}
356  };
357
358  template void f(X<int> *);
359  template void f2<int>(X<int> *);
360  template void f2<float>(X<int> *); // expected-note{{in instantiation of function template specialization 'PR10913::f2<float, int>' requested here}}
361}
362