1 // RUN: %clang_cc1 -fsyntax-only -verify %s 2 template<typename T> 3 void call_f0(T x) { 4 x.Base::f0(); 5 } 6 7 struct Base { 8 void f0(); 9 }; 10 11 struct X0 : Base { 12 typedef Base CrazyBase; 13 }; 14 15 void test_f0(X0 x0) { 16 call_f0(x0); 17 } 18 19 template<typename TheBase, typename T> 20 void call_f0_through_typedef(T x) { 21 typedef TheBase Base2; 22 x.Base2::f0(); 23 } 24 25 void test_f0_through_typedef(X0 x0) { 26 call_f0_through_typedef<Base>(x0); 27 } 28 29 template<typename TheBase, typename T> 30 void call_f0_through_typedef2(T x) { 31 typedef TheBase CrazyBase; // expected-note{{current scope}} 32 x.CrazyBase::f0(); // expected-error{{ambiguous}} \ 33 // expected-error 2{{no member named}} 34 } 35 36 struct OtherBase { }; 37 38 struct X1 : Base, OtherBase { 39 typedef OtherBase CrazyBase; // expected-note{{object type}} 40 }; 41 42 void test_f0_through_typedef2(X0 x0, X1 x1) { 43 call_f0_through_typedef2<Base>(x0); 44 call_f0_through_typedef2<OtherBase>(x1); // expected-note{{instantiation}} 45 call_f0_through_typedef2<Base>(x1); // expected-note{{instantiation}} 46 } 47 48 49 struct X2 { 50 operator int() const; 51 }; 52 53 template<typename T, typename U> 54 T convert(const U& value) { 55 return value.operator T(); // expected-error{{operator long}} 56 } 57 58 void test_convert(X2 x2) { 59 convert<int>(x2); 60 convert<long>(x2); // expected-note{{instantiation}} 61 } 62 63 template<typename T> 64 void destruct(T* ptr) { 65 ptr->~T(); 66 ptr->T::~T(); 67 } 68 69 template<typename T> 70 void destruct_intptr(int *ip) { 71 ip->~T(); 72 ip->T::~T(); 73 } 74 75 void test_destruct(X2 *x2p, int *ip) { 76 destruct(x2p); 77 destruct(ip); 78 destruct_intptr<int>(ip); 79 } 80 81 // PR5220 82 class X3 { 83 protected: 84 template <int> float* &f0(); 85 template <int> const float* &f0() const; 86 void f1() { 87 (void)static_cast<float*>(f0<0>()); 88 } 89 void f1() const{ 90 (void)f0<0>(); 91 } 92 }; 93 94 // Fun with template instantiation and conversions 95 struct X4 { 96 int& member(); 97 float& member() const; 98 }; 99 100 template<typename T> 101 struct X5 { 102 void f(T* ptr) { int& ir = ptr->member(); } 103 void g(T* ptr) { float& fr = ptr->member(); } 104 }; 105 106 void test_X5(X5<X4> x5, X5<const X4> x5c, X4 *xp, const X4 *cxp) { 107 x5.f(xp); 108 x5c.g(cxp); 109 } 110 111 // In theory we can do overload resolution at template-definition time on this. 112 // We should at least not assert. 113 namespace test4 { 114 struct Base { 115 template <class T> void foo() {} 116 }; 117 118 template <class T> struct Foo : Base { 119 void test() { 120 foo<int>(); 121 } 122 }; 123 } 124 125 namespace test5 { 126 template<typename T> 127 struct X { 128 using T::value; 129 130 T &getValue() { 131 return &value; 132 } 133 }; 134 } 135 136 // PR8739 137 namespace test6 { 138 struct A {}; 139 struct B {}; 140 template <class T> class Base; 141 template <class T> class Derived : public Base<T> { 142 A *field; 143 void get(B **ptr) { 144 // It's okay if at some point we figure out how to diagnose this 145 // at instantiation time. 146 *ptr = field; 147 } 148 }; 149 } 150