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
14namespace 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
31struct Opaque0 {};
32
33namespace 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
76namespace 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
119namespace 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
186namespace 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