1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
3 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
4 
5 template<typename T>
call_f0(T x)6 void call_f0(T x) {
7   x.Base::f0();
8 }
9 
10 struct Base {
11   void f0();
12 };
13 
14 struct X0 : Base {
15   typedef Base CrazyBase;
16 };
17 
test_f0(X0 x0)18 void test_f0(X0 x0) {
19   call_f0(x0);
20 }
21 
22 template<typename TheBase, typename T>
call_f0_through_typedef(T x)23 void call_f0_through_typedef(T x) {
24   typedef TheBase Base2;
25   x.Base2::f0();
26 }
27 
test_f0_through_typedef(X0 x0)28 void test_f0_through_typedef(X0 x0) {
29   call_f0_through_typedef<Base>(x0);
30 }
31 
32 template<typename TheBase, typename T>
call_f0_through_typedef2(T x)33 void call_f0_through_typedef2(T x) {
34   typedef TheBase CrazyBase;
35 #if __cplusplus <= 199711L
36   // expected-note@-2 {{lookup from the current scope refers here}}
37 #endif
38 
39   x.CrazyBase::f0(); // expected-error 2{{no member named}}
40 #if __cplusplus <= 199711L
41   // expected-error@-2 {{lookup of 'CrazyBase' in member access expression is ambiguous}}
42 #endif
43 
44 }
45 
46 struct OtherBase { };
47 
48 struct X1 : Base, OtherBase {
49   typedef OtherBase CrazyBase;
50 #if __cplusplus <= 199711L
51   // expected-note@-2 {{lookup in the object type 'X1' refers here}}
52 #endif
53 };
54 
test_f0_through_typedef2(X0 x0,X1 x1)55 void 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 
62 struct X2 {
63   operator int() const;
64 };
65 
66 template<typename T, typename U>
convert(const U & value)67 T convert(const U& value) {
68   return value.operator T(); // expected-error{{operator long}}
69 }
70 
test_convert(X2 x2)71 void test_convert(X2 x2) {
72   convert<int>(x2);
73   convert<long>(x2); // expected-note{{instantiation}}
74 }
75 
76 template<typename T>
destruct(T * ptr)77 void destruct(T* ptr) {
78   ptr->~T();
79   ptr->T::~T();
80 }
81 
82 template<typename T>
destruct_intptr(int * ip)83 void destruct_intptr(int *ip) {
84   ip->~T();
85   ip->T::~T();
86 }
87 
test_destruct(X2 * x2p,int * ip)88 void test_destruct(X2 *x2p, int *ip) {
89   destruct(x2p);
90   destruct(ip);
91   destruct_intptr<int>(ip);
92 }
93 
94 // PR5220
95 class X3 {
96 protected:
97   template <int> float* &f0();
98   template <int> const float* &f0() const;
f1()99   void f1() {
100     (void)static_cast<float*>(f0<0>());
101   }
f1() const102   void f1() const{
103     (void)f0<0>();
104   }
105 };
106 
107 // Fun with template instantiation and conversions
108 struct X4 {
109   int& member();
110   float& member() const;
111 };
112 
113 template<typename T>
114 struct X5 {
fX5115   void f(T* ptr) { int& ir = ptr->member(); }
gX5116   void g(T* ptr) { float& fr = ptr->member(); }
117 };
118 
test_X5(X5<X4> x5,X5<const X4> x5c,X4 * xp,const X4 * cxp)119 void 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.
126 namespace test4 {
127   struct Base {
footest4::Base128     template <class T> void foo() {}
129   };
130 
131   template <class T> struct Foo : Base {
testtest4::Foo132     void test() {
133       foo<int>();
134     }
135   };
136 }
137 
138 namespace test5 {
139   template<typename T>
140   struct X {
141     using T::value;
142 
getValuetest5::X143     T &getValue() {
144       return &value;
145     }
146   };
147 }
148 
149 // PR8739
150 namespace 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;
get(B ** ptr)156     void get(B **ptr) {
157       // It's okay if at some point we figure out how to diagnose this
158       // at instantiation time.
159       *ptr = field; // expected-error {{incompatible pointer types assigning to 'test6::B *' from 'test6::A *'}}
160     }
161   };
162 }
163 
164 namespace test7 {
165   struct C { void g(); };
166   template<typename T> struct A {
167     T x;
ftest7::A168     static void f() {
169       (x.g()); // expected-error {{invalid use of member 'x' in static member function}}
170     }
171   };
h()172   void h() { A<C>::f(); }
173 }
174