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