p1.cpp revision ea7390c7b384ce607bfc8fc13c01f37cfc3776f0
1// RUN: %clang_cc1 -faccess-control -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 {{previous definition is 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 {{redefinition of 'A' as different kind of symbol}}
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