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