xref: /aosp_15_r20/external/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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 
test0test1::B50     void test0() {
51       type t = 0;
52     }
53 
test1test1::B54     void test1() {
55       typedef struct A::hiding local;
56       struct hiding _ = local();
57     }
58 
test2test1::B59     void test2() {
60       union hiding _; // expected-error {{tag type that does not match previous}}
61     }
62 
test3test1::B63     void test3() {
64       char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
65     }
66 
test4test1::B67     void test4() {
68       enum tagname _ = enumerator;
69     }
70 
test5test1::B71     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 
test0test2::B93     void test0() {
94       type t = 0;
95     }
96 
test1test2::B97     void test1() {
98       typedef struct A::hiding local;
99       struct hiding _ = local();
100     }
101 
test2test2::B102     void test2() {
103       union hiding _; // expected-error {{tag type that does not match previous}}
104     }
105 
test3test2::B106     void test3() {
107       char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
108     }
109 
test4test2::B110     void test4() {
111       enum tagname _ = enumerator;
112     }
113 
test5test2::B114     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 
test3test3::B151     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 
test5test3::B161     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 
test6test3::C175     void test6() {
176       type t = 0;
177     }
178 
test7test3::C179     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   };
test(B b)235   void test(B b) {
236     B b2(b);
237     b2 = b;
238   }
239 }
240