p4.cpp revision 604e7f14d672af80ca5b9044f30f3dc23d37ddd5
1// RUN: clang-cc -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-error {{'typename' keyword used on a non-type}}
170    using typename A<T>::union_member; // expected-error {{'typename' keyword used on a non-type}}
171    using typename A<T>::enumerator; // expected-error {{'typename' keyword used on a non-type}}
172
173    void test6() {
174      type t = 0;
175    }
176
177    void test7() {
178      Opaque0 _ = hiding; // expected-error {{expected '(' for function-style cast or type construction}}
179    }
180  };
181
182  template struct C<int>; // expected-note {{in instantiation}}
183}
184
185namespace test4 {
186  struct Base {
187    int foo();
188  };
189
190  struct Unrelated {
191    int foo();
192  };
193
194  struct Subclass : Base {
195  };
196
197  namespace InnerNS {
198    int foo();
199  }
200
201  // We should be able to diagnose these without instantiation.
202  template <class T> struct C : Base {
203    using InnerNS::foo; // expected-error {{not a class}}
204    using Base::bar; // expected-error {{no member named 'bar'}}
205    using Unrelated::foo; // expected-error {{not a base class}}
206    using C::foo; // legal in C++03
207    using Subclass::foo; // legal in C++03
208
209    int bar(); //expected-note {{target of using declaration}}
210    using C::bar; // expected-error {{refers to its own class}}
211  };
212}
213