1// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify %s
2// RUN: %clang_cc1 -triple %ms_abi_triple -DMSABI -fsyntax-only -verify %s
3
4// Tests various places where requiring a complete type involves
5// instantiation of that type.
6
7template<typename T>
8struct X {
9  X(T);
10
11#ifdef MSABI
12// expected-error@+2{{data member instantiated with function type 'long (long)'}}
13#endif
14  T f; // expected-error{{data member instantiated with function type 'float (int)'}} \
15       // expected-error{{data member instantiated with function type 'int (int)'}} \
16       // expected-error{{data member instantiated with function type 'char (char)'}} \
17       // expected-error{{data member instantiated with function type 'short (short)'}} \
18       // expected-error{{data member instantiated with function type 'float (float)'}}
19};
20
21X<int> f() { return 0; }
22
23struct XField {
24  X<float(int)> xf; // expected-note{{in instantiation of template class 'X<float (int)>' requested here}}
25};
26
27void test_subscript(X<double> *ptr1, X<int(int)> *ptr2, int i) {
28  (void)ptr1[i];
29  (void)ptr2[i]; // expected-note{{in instantiation of template class 'X<int (int)>' requested here}}
30}
31
32void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2,
33                X<char(char)> *ptr3, X<short(short)> *ptr4) {
34  (void)(ptr1 + 5);
35  (void)(5 + ptr2);
36  (void)(ptr3 + 5); // expected-note{{in instantiation of template class 'X<char (char)>' requested here}}
37  (void)(5 + ptr4); // expected-note{{in instantiation of template class 'X<short (short)>' requested here}}
38}
39
40void test_new() {
41  (void)new X<float>(0);
42  (void)new X<float(float)>; // expected-note{{in instantiation of template class 'X<float (float)>' requested here}}
43}
44
45void test_memptr(X<long> *p1, long X<long>::*pm1,
46                 X<long(long)> *p2,
47#ifdef MSABI
48                 long (X<long(long)>::*pm2)(long)) { // expected-note{{in instantiation of template class 'X<long (long)>' requested here}}
49#else
50                 long (X<long(long)>::*pm2)(long)) {
51#endif
52  (void)(p1->*pm1);
53}
54
55// Reference binding to a base
56template<typename T>
57struct X1 { };
58
59template<typename T>
60struct X2 : public T { };
61
62void refbind_base(X2<X1<int> > &x2) {
63  X1<int> &x1 = x2;
64}
65
66// Enumerate constructors for user-defined conversion.
67template<typename T>
68struct X3 {
69  X3(T);
70};
71
72void enum_constructors(X1<float> &x1) {
73  X3<X1<float> > x3 = x1;
74}
75
76namespace PR6376 {
77  template<typename T, typename U> struct W { };
78
79  template<typename T>
80  struct X {
81    template<typename U>
82    struct apply {
83      typedef W<T, U> type;
84    };
85  };
86
87  template<typename T, typename U>
88  struct Y : public X<T>::template apply<U>::type { };
89
90  template struct Y<int, float>;
91}
92
93namespace TemporaryObjectCopy {
94  // Make sure we instantiate classes when we create a temporary copy.
95  template<typename T>
96  struct X {
97    X(T);
98  };
99
100  template<typename T>
101  void f(T t) {
102    const X<int> &x = X<int>(t);
103  }
104
105  template void f(int);
106}
107
108namespace PR7080 {
109  template <class T, class U>
110  class X
111  {
112    typedef char true_t;
113    class false_t { char dummy[2]; };
114    static true_t dispatch(U);
115    static false_t dispatch(...);
116    static T trigger();
117  public:
118    enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
119  };
120
121  template <class T>
122  class rv : public T
123  { };
124
125  bool x = X<int, rv<int>&>::value;
126}
127
128namespace pr7199 {
129  template <class T> class A; // expected-note {{template is declared here}}
130  template <class T> class B {
131    class A<T>::C field; // expected-error {{implicit instantiation of undefined template 'pr7199::A<int>'}}
132  };
133
134  template class B<int>; // expected-note {{in instantiation}}
135}
136
137namespace PR8425 {
138  template <typename T>
139  class BaseT {};
140
141  template <typename T>
142  class DerivedT : public BaseT<T> {};
143
144  template <typename T>
145  class FromT {
146  public:
147    operator DerivedT<T>() const { return DerivedT<T>(); }
148  };
149
150  void test() {
151    FromT<int> ft;
152    BaseT<int> bt(ft);
153  }
154}
155