174 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 5template<typename T>6void call_f0(T x) {7 x.Base::f0();8}9 10struct Base {11 void f0();12};13 14struct X0 : Base { 15 typedef Base CrazyBase;16};17 18void test_f0(X0 x0) {19 call_f0(x0);20}21 22template<typename TheBase, typename T>23void call_f0_through_typedef(T x) {24 typedef TheBase Base2;25 x.Base2::f0();26}27 28void test_f0_through_typedef(X0 x0) {29 call_f0_through_typedef<Base>(x0);30}31 32template<typename TheBase, typename T>33void call_f0_through_typedef2(T x) {34 typedef TheBase CrazyBase;35#if __cplusplus <= 199711L36 // expected-note@-2 {{lookup from the current scope refers here}}37#endif38 39 x.CrazyBase::f0(); // expected-error 2{{no member named}}40#if __cplusplus <= 199711L41 // expected-error@-2 {{lookup of 'CrazyBase' in member access expression is ambiguous}}42#endif43 44}45 46struct OtherBase { };47 48struct X1 : Base, OtherBase { 49 typedef OtherBase CrazyBase;50#if __cplusplus <= 199711L51 // expected-note@-2 {{lookup in the object type 'X1' refers here}}52#endif53};54 55void test_f0_through_typedef2(X0 x0, X1 x1) {56 call_f0_through_typedef2<Base>(x0);57 call_f0_through_typedef2<OtherBase>(x1); // expected-note{{instantiation}}58 call_f0_through_typedef2<Base>(x1); // expected-note{{instantiation}}59}60 61 62struct X2 {63 operator int() const;64};65 66template<typename T, typename U>67T convert(const U& value) {68 return value.operator T(); // expected-error{{operator long}}69}70 71void test_convert(X2 x2) {72 convert<int>(x2);73 convert<long>(x2); // expected-note{{instantiation}}74}75 76template<typename T>77void destruct(T* ptr) {78 ptr->~T();79 ptr->T::~T();80}81 82template<typename T>83void destruct_intptr(int *ip) {84 ip->~T();85 ip->T::~T();86}87 88void test_destruct(X2 *x2p, int *ip) {89 destruct(x2p);90 destruct(ip);91 destruct_intptr<int>(ip);92}93 94// PR522095class X3 {96protected:97 template <int> float* &f0();98 template <int> const float* &f0() const;99 void f1() {100 (void)static_cast<float*>(f0<0>());101 }102 void f1() const{103 (void)f0<0>();104 }105};106 107// Fun with template instantiation and conversions108struct X4 {109 int& member();110 float& member() const;111};112 113template<typename T>114struct X5 {115 void f(T* ptr) { int& ir = ptr->member(); }116 void g(T* ptr) { float& fr = ptr->member(); }117};118 119void test_X5(X5<X4> x5, X5<const X4> x5c, X4 *xp, const X4 *cxp) {120 x5.f(xp);121 x5c.g(cxp);122}123 124// In theory we can do overload resolution at template-definition time on this.125// We should at least not assert.126namespace test4 {127 struct Base {128 template <class T> void foo() {}129 };130 131 template <class T> struct Foo : Base {132 void test() {133 foo<int>();134 }135 };136}137 138namespace test5 {139 template<typename T>140 struct X {141 using T::value;142 143 T &getValue() {144 return &value;145 }146 };147}148 149// PR8739150namespace test6 {151 struct A {};152 struct B {};153 template <class T> class Base;154 template <class T> class Derived : public Base<T> {155 A *field;156 void get(B **ptr) {157 // It's okay if at some point we figure out how to diagnose this158 // at instantiation time.159 *ptr = field; // expected-error {{incompatible pointer types assigning to 'B *' from 'A *'}}160 }161 };162}163 164namespace test7 {165 struct C { void g(); };166 template<typename T> struct A {167 T x;168 static void f() {169 (x.g()); // expected-error {{invalid use of member 'x' in static member function}}170 }171 };172 void h() { A<C>::f(); }173}174