blob: 39818028bbad2dd3c43e62ec0e5b001598d8b23d [file] [log] [blame]
John McCalla742db02010-03-17 20:01:29 +00001// RUN: %clang_cc1 -faccess-control -verify -emit-llvm-only %s
John McCall9c86b512010-03-25 21:28:06 +00002
3namespace test0 {
John McCall02cace72009-08-28 07:59:38 +00004template <typename T> struct Num {
John McCallfd810b12009-08-14 02:03:10 +00005 T value_;
6
7public:
8 Num(T value) : value_(value) {}
9 T get() const { return value_; }
John McCall02cace72009-08-28 07:59:38 +000010
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
John McCallfd810b12009-08-14 02:03:10 +000023 friend Num operator+(const Num &a, const Num &b) {
24 return a.value_ + b.value_;
25 }
John McCall02cace72009-08-28 07:59:38 +000026
27 Num& operator+=(const Num& b) {
28 value_ += b.value_;
29 return *this;
30 }
John McCall82b9fb82009-09-02 19:32:14 +000031
32 class Representation {};
33 friend class Representation;
John McCallfd810b12009-08-14 02:03:10 +000034};
35
John McCall1a26c272009-09-02 01:07:03 +000036class A {
37 template <typename T> friend bool iszero(const A &a) throw();
38};
39
John McCall6b2becf2009-09-08 17:47:29 +000040template <class T> class B_iterator;
41template <class T> class B {
42 friend class B_iterator<T>;
43};
44
John McCall02cace72009-08-28 07:59:38 +000045int calc1() {
John McCallfd810b12009-08-14 02:03:10 +000046 Num<int> left = -1;
47 Num<int> right = 1;
48 Num<int> result = left + right;
49 return result.get();
50}
John McCall02cace72009-08-28 07:59:38 +000051
52int calc2() {
53 Num<int> x = 3;
John McCall2a29c4b2009-08-29 03:28:20 +000054 Num<int>::Rep<char> n = (char) 10;
John McCall02cace72009-08-28 07:59:38 +000055 Num<int> result = x * n;
56 return result.get();
57}
John McCall9c86b512010-03-25 21:28:06 +000058}
John McCalla742db02010-03-17 20:01:29 +000059
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}
John McCall0c01d182010-03-24 05:22:00 +000090
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
John McCall7ad650f2010-03-24 07:46:06 +0000100 bool value; // expected-note 2 {{declared private here}}
John McCall0c01d182010-03-24 05:22:00 +0000101 };
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) {
John McCall7ad650f2010-03-24 07:46:06 +0000110 if (b.value) // expected-error {{'value' is a private member of 'test3::Bool'}}
John McCall0c01d182010-03-24 05:22:00 +0000111 return value;
112 return value + 1;
113 }
114
115 template bool transform(Bool, bool);
John McCall7ad650f2010-03-24 07:46:06 +0000116 template int transform(Bool, int); // expected-note {{requested here}}
John McCall0c01d182010-03-24 05:22:00 +0000117
118 template class User<bool>;
119 template class User<int>; // expected-note {{requested here}}
John McCall93ba8572010-03-25 06:39:04 +0000120}
John McCall0c01d182010-03-24 05:22:00 +0000121
John McCall93ba8572010-03-25 06:39:04 +0000122namespace 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>;
John McCall0c01d182010-03-24 05:22:00 +0000144}
Douglas Gregor036ada22010-03-24 17:31:23 +0000145
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}
John McCall9c86b512010-03-25 21:28:06 +0000156
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}