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