1// RUN: %clang_cc1 -fsyntax-only -verify %s
2template<typename U, typename T>
3U f0(T t) {
4  return t.template get<U>();
5}
6
7template<typename U, typename T>
8int &f1(T t) {
9  // FIXME: When we pretty-print this, we lose the "template" keyword.
10  return t.U::template get<int&>();
11}
12
13struct X {
14  template<typename T> T get();
15};
16
17void test_f0(X x) {
18  int i = f0<int>(x);
19  int &ir = f0<int&>(x);
20}
21
22struct XDerived : public X {
23};
24
25void test_f1(XDerived xd) {
26  int &ir = f1<X>(xd);
27}
28
29// PR5213
30template <class T>
31struct A {};
32
33template<class T>
34class B
35{
36  A<T> a_;
37
38public:
39  void destroy();
40};
41
42template<class T>
43void
44B<T>::destroy()
45{
46  a_.~A<T>();
47}
48
49void do_destroy_B(B<int> b) {
50  b.destroy();
51}
52
53struct X1 {
54  int* f1(int);
55  template<typename T> float* f1(T);
56
57  static int* f2(int);
58  template<typename T> static float* f2(T);
59};
60
61void test_X1(X1 x1) {
62  float *fp1 = x1.f1<>(17);
63  float *fp2 = x1.f1<int>(3.14); // expected-warning {{implicit conversion from 'double' to 'int' changes value from 3.14 to 3}}
64  int *ip1 = x1.f1(17);
65  float *ip2 = x1.f1(3.14);
66
67  float* (X1::*mf1)(int) = &X1::f1;
68  float* (X1::*mf2)(int) = &X1::f1<>;
69  float* (X1::*mf3)(float) = &X1::f1<float>;
70
71  float* (*fp3)(int) = &X1::f2;
72  float* (*fp4)(int) = &X1::f2<>;
73  float* (*fp5)(float) = &X1::f2<float>;
74  float* (*fp6)(int) = X1::f2;
75  float* (*fp7)(int) = X1::f2<>;
76  float* (*fp8)(float) = X1::f2<float>;
77}
78
79template<int A> struct X2 {
80  int m;
81};
82
83template<typename T>
84struct X3 : T { };
85
86template<typename T>
87struct X4 {
88  template<typename U>
89  void f(X2<sizeof(X3<U>().U::m)>);
90};
91
92void f(X4<X3<int> > x4i) {
93  X2<sizeof(int)> x2;
94  x4i.f<X2<sizeof(int)> >(x2);
95}
96
97template<typename T>
98struct X5 {
99  template<typename U>
100  void f();
101
102  void g() {
103    this->f<T*>();
104  }
105};
106
107namespace PR6021 {
108  template< class T1, class T2 >
109  class Outer
110  {
111  public: // Range operations
112    template< class X > X tmpl( const X* = 0 ) const;
113
114    struct Inner
115    {
116      const Outer& o;
117
118      template< class X >
119      operator X() const
120      {
121        return o.tmpl<X>();
122      }
123    };
124  };
125}
126
127namespace rdar8198511 {
128  template<int, typename U>
129  struct Base {
130    void f();
131  };
132
133  template<typename T>
134  struct X0 : Base<1, T> { };
135
136  template<typename T>
137  struct X1 {
138    X0<int> x0;
139
140    void f() {
141      this->x0.Base<1, int>::f();
142    }
143  };
144}
145