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