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