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