233 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify %s2// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s3// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s4 5// C++03 [namespace.udecl]p4:6// A using-declaration used as a member-declaration shall refer to a7// member of a base class of the class being defined, shall refer to8// a member of an anonymous union that is a member of a base class9// of the class being defined, or shall refer to an enumerator for10// an enumeration type that is a member of a base class of the class11// being defined.12 13// There is no directly analogous paragraph in C++0x, and the feature14// works sufficiently differently there that it needs a separate test.15 16namespace 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 33struct Opaque0 {};34 35namespace 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 51 void test0() {52 type t = 0;53 }54 55 void test1() {56 typedef struct A::hiding local;57 struct hiding _ = local();58 }59 60 void test2() {61 union hiding _; // expected-error {{tag type that does not match previous}}62 }63 64 void test3() {65 char array[sizeof(union_member) == sizeof(double) ? 1 : -1];66 }67 68 void test4() {69 enum tagname _ = enumerator;70 }71 72 void test5() {73 Opaque0 _ = hiding;74 }75 };76}77 78namespace 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 94 void test0() {95 type t = 0;96 }97 98 void test1() {99 typedef struct A::hiding local;100 struct hiding _ = local();101 }102 103 void test2() {104 union hiding _; // expected-error {{tag type that does not match previous}}105 }106 107 void test3() {108 char array[sizeof(union_member) == sizeof(double) ? 1 : -1];109 }110 111 void test4() {112 enum tagname _ = enumerator;113 }114 115 void test5() {116 Opaque0 _ = hiding;117 }118 };119}120 121namespace 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 fixed140#if 0141 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#endif151 152 void test3() {153 char array[sizeof(union_member) == sizeof(double) ? 1 : -1];154 }155 156#if 0157 void test4() {158 enum tagname _ = enumerator;159 }160#endif161 162 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 176 void test6() {177 type t = 0;178 }179 180 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 188namespace 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; // expected-error {{refers to its own class}}210 using Subclass::foo; // expected-error {{refers into 'Subclass', which is not a base class}}211 int bar();212 using C::bar; // expected-error {{refers to its own class}}213 };214}215 216namespace test5 {217 struct B;218 struct A {219 A(const B&);220 B &operator=(const B&);221 };222 struct B : A {223#if __cplusplus >= 201103L224 using A::A;225#endif226 using A::operator=;227 };228 void test(B b) {229 B b2(b);230 b2 = b;231 }232}233