1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s |
3 | |
4 | // C++03 [namespace.udecl]p4: |
5 | // A using-declaration used as a member-declaration shall refer to a |
6 | // member of a base class of the class being defined, shall refer to |
7 | // a member of an anonymous union that is a member of a base class |
8 | // of the class being defined, or shall refer to an enumerator for |
9 | // an enumeration type that is a member of a base class of the class |
10 | // being defined. |
11 | |
12 | // There is no directly analogous paragraph in C++0x, and the feature |
13 | // works sufficiently differently there that it needs a separate test. |
14 | |
15 | namespace test0 { |
16 | namespace NonClass { |
17 | typedef int type; |
18 | struct hiding {}; |
19 | int hiding; |
20 | static union { double union_member; }; |
21 | enum tagname { enumerator }; |
22 | } |
23 | |
24 | class Test0 { |
25 | using NonClass::type; // expected-error {{not a class}} |
26 | using NonClass::hiding; // expected-error {{not a class}} |
27 | using NonClass::union_member; // expected-error {{not a class}} |
28 | using NonClass::enumerator; // expected-error {{not a class}} |
29 | }; |
30 | } |
31 | |
32 | struct Opaque0 {}; |
33 | |
34 | namespace test1 { |
35 | struct A { |
36 | typedef int type; |
37 | struct hiding {}; // expected-note {{previous use is here}} |
38 | Opaque0 hiding; |
39 | union { double union_member; }; |
40 | enum tagname { enumerator }; |
41 | }; |
42 | |
43 | struct B : A { |
44 | using A::type; |
45 | using A::hiding; |
46 | using A::union_member; |
47 | using A::enumerator; |
48 | using A::tagname; |
49 | |
50 | void test0() { |
51 | type t = 0; |
52 | } |
53 | |
54 | void test1() { |
55 | typedef struct A::hiding local; |
56 | struct hiding _ = local(); |
57 | } |
58 | |
59 | void test2() { |
60 | union hiding _; // expected-error {{tag type that does not match previous}} |
61 | } |
62 | |
63 | void test3() { |
64 | char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; |
65 | } |
66 | |
67 | void test4() { |
68 | enum tagname _ = enumerator; |
69 | } |
70 | |
71 | void test5() { |
72 | Opaque0 _ = hiding; |
73 | } |
74 | }; |
75 | } |
76 | |
77 | namespace test2 { |
78 | struct A { |
79 | typedef int type; |
80 | struct hiding {}; // expected-note {{previous use is here}} |
81 | int hiding; |
82 | union { double union_member; }; |
83 | enum tagname { enumerator }; |
84 | }; |
85 | |
86 | template <class T> struct B : A { |
87 | using A::type; |
88 | using A::hiding; |
89 | using A::union_member; |
90 | using A::enumerator; |
91 | using A::tagname; |
92 | |
93 | void test0() { |
94 | type t = 0; |
95 | } |
96 | |
97 | void test1() { |
98 | typedef struct A::hiding local; |
99 | struct hiding _ = local(); |
100 | } |
101 | |
102 | void test2() { |
103 | union hiding _; // expected-error {{tag type that does not match previous}} |
104 | } |
105 | |
106 | void test3() { |
107 | char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; |
108 | } |
109 | |
110 | void test4() { |
111 | enum tagname _ = enumerator; |
112 | } |
113 | |
114 | void test5() { |
115 | Opaque0 _ = hiding; |
116 | } |
117 | }; |
118 | } |
119 | |
120 | namespace test3 { |
121 | struct hiding {}; |
122 | |
123 | template <class T> struct A { |
124 | typedef int type; // expected-note {{target of using declaration}} |
125 | struct hiding {}; |
126 | Opaque0 hiding; // expected-note {{target of using declaration}} |
127 | union { double union_member; }; // expected-note {{target of using declaration}} |
128 | enum tagname { enumerator }; // expected-note 2 {{target of using declaration}} |
129 | }; |
130 | |
131 | template <class T> struct B : A<T> { |
132 | using A<T>::type; // expected-error {{dependent using declaration resolved to type without 'typename'}} |
133 | using A<T>::hiding; |
134 | using A<T>::union_member; |
135 | using A<T>::enumerator; |
136 | using A<T>::tagname; // expected-error {{dependent using declaration resolved to type without 'typename'}} |
137 | |
138 | // FIXME: re-enable these when the various bugs involving tags are fixed |
139 | #if 0 |
140 | void test1() { |
141 | typedef struct A<T>::hiding local; |
142 | struct hiding _ = local(); |
143 | } |
144 | |
145 | void test2() { |
146 | typedef struct A<T>::hiding local; |
147 | union hiding _ = local(); |
148 | } |
149 | #endif |
150 | |
151 | void test3() { |
152 | char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; |
153 | } |
154 | |
155 | #if 0 |
156 | void test4() { |
157 | enum tagname _ = enumerator; |
158 | } |
159 | #endif |
160 | |
161 | void test5() { |
162 | Opaque0 _ = hiding; |
163 | } |
164 | }; |
165 | |
166 | template struct B<int>; // expected-note {{in instantiation}} |
167 | |
168 | template <class T> struct C : A<T> { |
169 | using typename A<T>::type; |
170 | using typename A<T>::hiding; // expected-note {{declared here}} \ |
171 | // expected-error {{'typename' keyword used on a non-type}} |
172 | using typename A<T>::union_member; // expected-error {{'typename' keyword used on a non-type}} |
173 | using typename A<T>::enumerator; // expected-error {{'typename' keyword used on a non-type}} |
174 | |
175 | void test6() { |
176 | type t = 0; |
177 | } |
178 | |
179 | void test7() { |
180 | Opaque0 _ = hiding; // expected-error {{does not refer to a value}} |
181 | } |
182 | }; |
183 | |
184 | template struct C<int>; // expected-note {{in instantiation}} |
185 | } |
186 | |
187 | namespace test4 { |
188 | struct Base { |
189 | int foo(); |
190 | }; |
191 | |
192 | struct Unrelated { |
193 | int foo(); |
194 | }; |
195 | |
196 | struct Subclass : Base { |
197 | }; |
198 | |
199 | namespace InnerNS { |
200 | int foo(); |
201 | } |
202 | |
203 | // We should be able to diagnose these without instantiation. |
204 | template <class T> struct C : Base { |
205 | using InnerNS::foo; // expected-error {{not a class}} |
206 | using Base::bar; // expected-error {{no member named 'bar'}} |
207 | using Unrelated::foo; // expected-error {{not a base class}} |
208 | using C::foo; // legal in C++03 |
209 | using Subclass::foo; // legal in C++03 |
210 | #if __cplusplus >= 201103L |
211 | // expected-error@-3 {{refers to its own class}} |
212 | // expected-error@-3 {{refers into 'Subclass::', which is not a base class}} |
213 | #endif |
214 | |
215 | int bar(); |
216 | #if __cplusplus < 201103L |
217 | // expected-note@-2 {{target of using declaration}} |
218 | #endif |
219 | using C::bar; // expected-error {{refers to its own class}} |
220 | }; |
221 | } |
222 | |
223 | namespace test5 { |
224 | struct B; |
225 | struct A { |
226 | A(const B&); |
227 | B &operator=(const B&); |
228 | }; |
229 | struct B : A { |
230 | #if __cplusplus >= 201103L |
231 | using A::A; |
232 | #endif |
233 | using A::operator=; |
234 | }; |
235 | void test(B b) { |
236 | B b2(b); |
237 | b2 = b; |
238 | } |
239 | } |
240 | |