1 // RUN: %clang_cc1 -fsyntax-only %s -verify
2 
3 // C++'0x [namespace.memdef] p3:
4 //   Every name first declared in a namespace is a member of that namespace. If
5 //   a friend declaration in a non-local class first declares a class or
6 //   function the friend class or function is a member of the innermost
7 //   enclosing namespace.
8 
9 namespace N {
10   struct S0 {
11     friend struct F0;
12     friend void f0(int);
13     struct F0 member_func();
14   };
15   struct F0 { };
16   F0 f0() { return S0().member_func(); }
17 }
18 N::F0 f0_var = N::f0();
19 
20 // Ensure we can handle attaching friend declarations to an enclosing namespace
21 // with multiple contexts.
22 namespace N { struct S1 { struct IS1; }; }
23 namespace N {
24   struct S1::IS1 {
25     friend struct F1;
26     friend void f1(int);
27     struct F1 member_func();
28   };
29   struct F1 { };
30   F1 f1() { return S1::IS1().member_func(); }
31 }
32 N::F1 f1_var = N::f1();
33 
34 //   The name of the friend is not found by unqualified lookup (3.4.1) or by
35 //   qualified lookup (3.4.3) until a matching declaration is provided in that
36 //   namespace scope (either before or after the class definition granting
37 //   friendship). If a friend function is called, its name may be found by the
38 //   name lookup that considers functions from namespaces and classes
39 //   associated with the types of the function arguments (3.4.2). If the name
40 //   in a friend declaration is neither qualified nor a template-id and the
41 //   declaration is a function or an elaborated-type-specifier, the lookup to
42 //   determine whether the entity has been previously declared shall not
43 //   consider any scopes outside the innermost enclosing namespace.
44 
45 template<typename T> struct X0 { };
46 struct X1 { };
47 
48 struct Y {
49   template<typename T> union X0;
50   template<typename T> friend union X0;
51 
52   union X1;
53   friend union X1;
54 };
55 
56 namespace N {
57   namespace M {
58     template<typename T> class X;
59   }
60 }
61 
62 namespace N3 {
63   class Y {
64     template<typename T> friend class N::M::X;
65   };
66 }
67 
68 // FIXME: Woefully inadequate for testing
69 
70 // Friends declared as template-ids aren't subject to the restriction
71 // on innermost namespaces.
72 // rdar://problem/8552377
73 namespace test5 {
74   template <class T> void f(T);
75   namespace ns {
76     class A {
77       friend void f<int>(int);
78       static void foo(); // expected-note 2 {{declared private here}}
79     };
80 
81     // Note that this happens without instantiation.
82     template <class T> void f(T) {
83       A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}}
84     }
85   }
86 
87   template <class T> void f(T) {
88     ns::A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}}
89   }
90 
91   template void f<int>(int);
92   template void f<long>(long); //expected-note {{instantiation}}
93 }
94 
95 // rdar://13393749
96 namespace test6 {
97   class A;
98   namespace ns {
99     class B {
100       static void foo(); // expected-note {{implicitly declared private here}}
101       friend union A;
102     };
103 
104     union A {
105       void test() {
106         B::foo();
107       }
108     };
109   }
110 
111   class A {
112     void test() {
113       ns::B::foo(); // expected-error {{'foo' is a private member of 'test6::ns::B'}}
114     }
115   };
116 }
117 
118 // We seem to be following a correct interpretation with these, but
119 // the standard could probably be a bit clearer.
120 namespace test7a {
121   namespace ns {
122     class A;
123   }
124 
125   using namespace ns;
126   class B {
127     static void foo();
128     friend class A;
129   };
130 
131   class ns::A {
132     void test() {
133       B::foo();
134     }
135   };
136 }
137 namespace test7b {
138   namespace ns {
139     class A;
140   }
141 
142   using ns::A;
143   class B {
144     static void foo();
145     friend class A;
146   };
147 
148   class ns::A {
149     void test() {
150       B::foo();
151     }
152   };
153 }
154 namespace test7c {
155   namespace ns1 {
156     class A;
157   }
158 
159   namespace ns2 {
160     // ns1::A appears as if declared in test7c according to [namespace.udir]p2.
161     // I think that means we aren't supposed to find it.
162     using namespace ns1;
163     class B {
164       static void foo(); // expected-note {{implicitly declared private here}}
165       friend class A;
166     };
167   }
168 
169   class ns1::A {
170     void test() {
171       ns2::B::foo(); // expected-error {{'foo' is a private member of 'test7c::ns2::B'}}
172     }
173   };
174 }
175 namespace test7d {
176   namespace ns1 {
177     class A;
178   }
179 
180   namespace ns2 {
181     // Honor the lexical context of a using-declaration, though.
182     using ns1::A;
183     class B {
184       static void foo();
185       friend class A;
186     };
187   }
188 
189   class ns1::A {
190     void test() {
191       ns2::B::foo();
192     }
193   };
194 }
195